检查布尔数组是否包含true的最快方法

时间:2012-12-03 05:51:20

标签: java

我有arrayboolean个条目:

boolean[] myBooleanArray = new boolean[24];

目前我检查它是否包含如此:

Arrays.asList(myBooleanArray).contains(true);

这是检查布尔数组的最快方法吗?如果没有,执行此检查的最快方法是什么?

编辑:

我通过在Android 4.03 Samsung S2设备上将其作为应用程序运行,将您的答案中的方法计时如下:

boolean[] myBooleanArray = new boolean[24];

long startTime = System.nanoTime();
suggestedMethod(myBooleanArray);
long endTime = System.nanoTime();

long duration = endTime - startTime;
Log.i("timetest", Long.toString(duration));

时间排名超过五次,最快的是第一次:

  1. 在5334和11584 ns之间:

    for (boolean value : myBooleanArray) {
        if (value) {
            return true;
        }
    }
    return false;
    
  2. 在160542和171417之间:

    Arrays.asList(myBooleanArray).contains(true);
    
  3. 191833至205750 ns:

    Booleans.contains(myBooleanArray, true);
    

7 个答案:

答案 0 :(得分:10)

只需遍历数组

for(boolean value: myBooleanArray){
  if(value){ return true;}
}
return false;

答案 1 :(得分:6)

如果您使用的是Guava库(它有很多有用的东西):

Booleans.contains(myBooleanArray, true);

JavaDoc

此方法的文档也描述了另一种方法。您可以将boolean[]替换为BitSet(应该提高内存效率)并调用!bitSet.isEmpty()以检查至少有一位是否为真。

答案 2 :(得分:4)

一般来说,如果您有任何数组(或List),那么在其中查找项目的最快/唯一方法是迭代数组,直到找到您要查找的内容。这是数组/ List的限制之一。

对于24个元素的数组,无论如何我都不会担心。如果您有数百万个项目并且预期很少true(或可能没有),那么将数据封装在类中是有意义的:

public class BooleanArray
{
    boolean[] arr = new boolean[SIZE]; // or get size from a constructor
    boolean anyTrue = false;

    boolean get(int index) {
        return arr[index];
    }

    boolean set(int index, boolean value) {
        arr[index] = value;
        anyTrue |= value;
    }

    boolean containsAnyTrues() {
        return anyTrue;
    }
}

重申一下,我不建议您使用24个元素。我的意思是更多的例子,你的数据结构应该支持预期的用例。如果预期的用例是“很多元素,非常稀疏true,需要找出是否有true s”,那么您对最快方式的关注更为相关,并且数据结构像上面的那个会很有用。

答案 3 :(得分:1)

根据this previous question迭代数组大致相同,使用增强for或normal,因为两者都使用数组访问。所以只需迭代你的数组:

public boolean containsTrue(boolean[] array){

    for(boolean val : array){
        if(val)
            return true;
    }

    return false;
}

答案 4 :(得分:1)

如果你有一个0和1的数组,你可以简单地OR每个元素。如果你得到1,你知道至少有一个是真的。

答案 5 :(得分:0)

如果未绑定到布尔值的 Array ,则应查看类java.util.BitSet。尽管有名称,但它更像数组而不是集合。

BitSet.isEmpty方法正在回答您的问题,即“数组”中是否有true,它的实现方式为:

public boolean isEmpty()
{
    return wordsInUse == 0;
}

我怀疑您能得到更快的支票...

但是价格必须在其他地方支付:设置/取消设置值可能只需要boolean []就更昂贵了。

答案 6 :(得分:0)

如果您知道数组的大小,并且数组很大。例如。 24很小,因此很难进行改进。 Arrays.mismatch似乎要快一些。

import java.util.Arrays;
import java.util.Random;

public class BenchMark{
    final static int N = Short.MAX_VALUE;
    static boolean[] base = new boolean[N];
    static boolean any1(boolean[] test){
        return Arrays.mismatch(base, test)==-1;
    }
    static boolean any2(boolean[] test){
        for(boolean b: test)
            if(b) return true;
        return false;
    }
    public static void main(String[] args){
        boolean[] test = new boolean[N];
        Random r = new Random(1);
        int last = 0;
        long start = System.nanoTime();
        int p = 0;
        for(int i = 0; i<100000; i++){
            test[last] = false;
            int s = r.nextInt(2);
            if(s == 0){
                last = r.nextInt(test.length);
                test[last] = true;
            } 
            if(any2(test)){
                p++;
            }
        }
        System.out.println( ( p + " in " + (System.nanoTime() - start ) / 1e9 ) + " seconds");
    }
}

我没有设置适当的基准,但是此输出显示any1比标准循环技术any2快4-5倍。

要了解原因,请查看jdk源代码。我们发现vectorizedMismatch似乎正在使用不安全的类将值转换为long并比较long值。