8

我有一个array条目boolean

boolean[] myBooleanArray = new boolean[24];

目前我检查它是否包含 true 像这样:

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 ns 之间:

    Arrays.asList(myBooleanArray).contains(true);
    
  3. 在 191833 和 205750 ns 之间:

    Booleans.contains(myBooleanArray, true);
    
4

7 回答 7

14

只需遍历数组

for(boolean value: myBooleanArray){
  if(value){ return true;}
}
return false;
于 2012-12-03T05:53:32.640 回答
6

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

Booleans.contains(myBooleanArray, true);

( JavaDoc )

该方法的文档还描述了另一种方法。您可以将 a 替换为boolean[]a BitSet(应该更节省内存)并调用!bitSet.isEmpty()以检查至少一位是否为真。

于 2012-12-03T05:58:32.527 回答
4

一般来说,如果您有一个数组(或List),在其中查找项目的最快/唯一方法是遍历数组,直到找到您要查找的内容。List这是 arrays/ s的限制之一。

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

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的 s,需要找出是否有任何trues”,那么您对最快方式的关注更相关,并且像上面这样的数据结构会很有用。

于 2012-12-03T06:01:10.153 回答
2

根据这个先前的问题,使用增强的 for 或普通的 for 遍历数组几乎是相同的,因为两者都使用数组访问。所以只需遍历你的数组:

public boolean containsTrue(boolean[] array){

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

    return false;
}
于 2012-12-03T05:58:20.327 回答
0

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

于 2012-12-03T07:18:55.093 回答
0

如果你没有绑定到布尔数组,你应该看看 class java.util.BitSet。尽管有这个名字,它更像是数组而不是集合。

如果“数组”中有任何内容,该方法BitSet.isEmpty正在回答您的问题true,并且它被实现为:

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

我怀疑您能否获得更快的检查……</p>

但是必须在其他地方付出代价:设置/取消设置值可能比仅仅boolean [].

于 2020-04-23T09:20:47.817 回答
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");
    }
}

我没有设置适当的基准测试,但它的输出显示any1any2标准循环技术快 4-5 倍。

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

于 2020-04-23T10:49:23.557 回答