我有array
个boolean
个条目:
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));
时间排名超过五次,最快的是第一次:
在5334和11584 ns之间:
for (boolean value : myBooleanArray) {
if (value) {
return true;
}
}
return false;
在160542和171417之间:
Arrays.asList(myBooleanArray).contains(true);
191833至205750 ns:
Booleans.contains(myBooleanArray, true);
答案 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值。