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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13677872/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 13:34:19  来源:igfitidea点击:

Fastest way to check if an array of boolean contains true

java

提问by Pierre Rymiortz

I have an arrayof booleanentries:

我有一个arrayboolean条目:

boolean[] myBooleanArray = new boolean[24];

Currently i check if it contains true like so:

目前我检查它是否包含 true ,如下所示:

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

Is this the fastestway to check an array of boolean? If not, what is the fastest way to perform this check?

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

EDIT:

编辑:

I timed the methods in your answers as follows by running it as an app on an Android 4.03 Samsung S2 device:

我通过在 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));

Time ranking over five runs were, with fastest first:

五次运行的时间排名是,最快的第一名:

  1. Between 5334 and 11584 ns:

    for (boolean value : myBooleanArray) {
        if (value) {
            return true;
        }
    }
    return false;
    
  2. Between 160542 and 171417 ns:

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

    Booleans.contains(myBooleanArray, true);
    
  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);
    

回答by Jigar Joshi

Just iterate through array

只需遍历数组

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

回答by Philipp Wendler

If you are using the Guavalibrary (which has a lot of useful stuff):

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

Booleans.contains(myBooleanArray, true);

(JavaDoc)

( JavaDoc)

The documentation of this method also describes another way. You can replace a boolean[]with a BitSet(should be more memory efficient) and call !bitSet.isEmpty()to check whether at least one bit is true.

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

回答by yshavit

Generally speaking, if you have an array (or List) of anything, the fastest/onlyest way to look for an item in it is to iterate over the array until you find what you're looking for. That's one of the limitations of arrays/Lists.

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

For an array of 24 elements, I wouldn't worry about this anyway. If you had millions of items and expected very few trues (or possibly none), then it could make sense to encapsulate the data in a class:

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

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;
    }
}

To reiterate, I don't suggest this for your array of 24 elements. I mean it more of an example that your data structure should support the expected use case. If the expected use case is "lots of elements, very sparse trues, need to find out if there are any trues" then your concern for the fastest way is more relevant, and a data structure like the one above would be useful.

重申一下,我不建议将这个用于 24 个元素的数组。我的意思是,您的数据结构应该支持预期的用例。如果预期的用例是“很多元素,非常稀疏的trues,需要找出是否有任何trues”,那么您对最快方法的关注更相关,并且像上面这样的数据结构会很有用。

回答by ElderMael

According to this previous questioniterating over an array is mostly the same using enhanced for or normal for because both use array accesses . So just iterate over your array:

根据这个先前的问题,迭代数组与使用 Enhanced for 或 normal for 大致相同,因为两者都使用 array accesses 。所以只需迭代你的数组:

public boolean containsTrue(boolean[] array){

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

    return false;
}

回答by AbuZubair

If you had an array of 0's and 1's, you could simply OR every element. If you get a 1, you know there is atleast one TRUE.

如果您有一个由 0 和 1 组成的数组,则可以简单地对每个元素进行 OR 运算。如果你得到一个 1,你就知道至少有一个 TRUE。

回答by tquadrat

If you are not bound to an Arrayof boolean, you should give a look to the class java.util.BitSet. Despite the name, it is more array-like than set-like.

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

The method BitSet.isEmptyis answering your question if there is any truein the "Array", and it is implemented as:

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

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

I doubt that you can get a faster check …

我怀疑你能不能得到更快的检查……

But the price has to be paid elsewhere: setting/unsetting a value might be more expensive as for a mere boolean [].

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

回答by matt

If you know the size of the array, and the array is large. Eg. 24 is pretty small so it would be hard to improve. Arrays.mismatch seems to be a bit quicker.

如果你知道数组的大小,并且数组很大。例如。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");
    }
}

I didn't setup a proper benchmark, but the output from this shows any1to be about 4-5 times faster than any2, the standard loop technique.

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

To understand why, looking in the jdk source code. We find vectorizedMismatchwhich appears to be using the unsafe class to cast the values to a long and comparing the long values.

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