检查布尔数组中所有值是否为true的最优雅方法是什么?

88

我在Java中有一个布尔数组:

boolean[] myArray = new boolean[10];

检查所有值是否为真的最优雅方法是什么?


2
如果你真的需要快速完成这个操作,那么最好将标志存储在intlong(甚至是*long[]*)中,并自己进行“数学”计算。然后你可以一次检查多达32或64个值。但是我怀疑你所说的那个地方是否会成为瓶颈。 - TacticalCoder
@donturner 你的意思是最快指计算速度快,还是指编程速度快(代码量少)? - whirlwin
2
非常感谢您的快速回复。我所指的“最快”是指“最快写出来”,而不是执行速度最快。也许我应该说“最优雅”。 - donturner
循环并在一个不符合条件时跳出。为了提高速度,最好使用整数或哈希映射。 - DGoiko
12个回答

98
public static boolean areAllTrue(boolean[] array)
{
    for(boolean b : array) if(!b) return false;
    return true;
}

21
这可能是个人偏好,但如果未来该方法需要另一个输入时,我会使用isAllTrue(boolean... array)。它仍然接受数组,但我们不想限制可能的未来用户。 - Ky -
说实话,我认为这是这里少数合理的答案之一。其他答案使用其他JVM语言、依赖项、Boolean(装箱)或者只是不必要地复杂化了。任何强调速度的答案都没有包含任何微基准测试数据,至少能够让人们对其在他们的机器上的表现有个大致的了解。在我看来,保持简单,只需要采用普通方法即可。 - Seth Falco

94
Arrays.asList(myArray).contains(false)

4
这里有一条命令:简洁明了,查找速度为O(n),有什么不喜欢的呢? - chrismarx
36
只有当它是一个Boolean[]时才有效,而不是boolean[]。因为你无法使用原始类型创建List,所以你最终会得到一个包含List<boolean[]>的Arrays.asList(boolean[]),该列表永远不包含false,因为它总是包含数组。 - David Georg Reichelt
@DavidGeorgReichelt 我不认为这是提问者的主要关注点。它明确说明了“从布尔数组”所以... - Ian Elvister
@acorello 哦,我现在明白了,感谢您的解释。我已经删除了我的原始评论 :) - Samir
1
@acorell 什么评论?XDD - Pablo LION

40

在Java 8中,您可以执行:

boolean isAllTrue = Arrays.asList(myArray).stream().allMatch(val -> val == true);

或者更短:

boolean isAllTrue = Arrays.stream(myArray).allMatch(Boolean::valueOf);

注意:你需要使用Boolean[]才能使此解决方案正常工作。因为你不能拥有原始类型的列表。


9
Arrays.asList(myArray).stream().allMatch(Boolean::booleanValue) 可以用于判断全部为true或全部为false - ccpizza
1
Arrays.asList(myArray).stream().allMatch(val -> Boolean.TRUE.equals(val)); 这段代码还可以正确处理数组中存在空值的情况。 - Ihor M.
要检查是否明确为真,可以使用Arrays.asList(myArray).stream().allMatch(Boolean.TRUE::equals)。 - undefined

18

这取决于您需要多少次查找此信息,如果超过一次:

Set<Boolean> flags = new HashSet<Boolean>(myArray);
flags.contains(false);

否则是一个短路循环:

for (i = 0; i < myArray.length; i++) {
  if (!myArray[i]) return false;
}
return true;

bool 不是 Java?!而且在每次交互中访问长度 - foreach 更快(至少)。但 Set 的想法很酷 - +1。 - user85421
1
@CarlosHeuberger 很好的发现,最近一直在使用C#,把我的bools和booleans搞混了! - Rich O'Kelly
@CarlosHeuberger 等待每个应该比简单循环更快吗?如果JIT可以内联所有内容并相应地进行优化,则迭代器解决方案可能与直接访问一样快,但肯定不会更快(另一方面,对数组长度的CSE几乎肯定会发生)。从理论上讲,在x86上从length() - 1开始并在0处停止可能略微更快,但这甚至不再是微观优化。 - Voo
3
-1是因为顶部的例子无法编译通过: 出现了意外的类型错误, 需要一个引用类型, 但却得到了布尔类型。 - Ky -
1
@AmirPashazadeh 最初的问题是“最快的方法是什么...”,而不是“最优雅的方法是什么...”。是的,创建会更慢,但是在 HashSet 中查找是 O(1),而在 ArrayList 中是 O(n),因此我提到了 OP 想要多少次查找这些信息。由于 Java 缺乏具体化的泛型,因此还值得提到在 contains 方法中装箱布尔值的成本,但是在任何最近的 JVM 上,这将形成一个 gen 0 可收集对象,成本应该可以忽略不计。也可以通过传递 Boolean.False 来减轻这种情况。 - Rich O'Kelly
显示剩余4条评论

13

我简直不敢相信没有 BitSet 的解决方案。

BitSet 是一种对比特位的抽象,通过使用它我们不再需要使用 boolean[] 进行更高级别的交互了,因为它已经包含了大部分需要的方法。在批量操作中,它也非常快速,因为它内部使用 long 值存储比特位,而不像 boolean[] 一样逐个检查每个位。

BitSet myBitSet = new BitSet(10);
// fills the bitset with ten true values
myBitSet.set(0, 10);

针对您的特定情况,我会使用cardinality()方法:

if (myBitSet.cardinality() == myBitSet.size()) {
    // do something, there are no false bits in the bitset
}

另一个选择是使用Guava

return Booleans.contains(myArray, true);

1
我认为使用BitSet是一个很好的想法。然而,在比较基数(计算设置为true的位数)和长度(计算所有位置,包括真和假,直到最后一个设置为true的位置)时需要小心。我遇到了将与具有尾随false的ListArray相关联的BitSet的长度进行比较的情况 - 也就是说,我需要的是ListArray的长度而不是BitSet的长度。 - KTys
1
这就是为什么你应该使用 .size() 而不是 .length()。 - Mark Renouf
我简直不敢相信没有 Apache Commons 的解决方案。哦,等等,现在有了一个。;) - Gerold Broser
@MarkRenouf请再次查看文档并进行一些测试,KTys是正确的。例如,在我的Java设置中,.size()返回64,而不管n(... BitSet(n))。 !!!糟糕的建议: 当上下文正确时,有人可以使用.length()确保最后一个值是正确的,并且永远不会更改。 - Jaja

11

2
为了澄清可能会困惑的人们,如果他们无法访问BooleanUtils,那么它是Apache Commons Lang的一部分,因此您首先必须将其添加为依赖项。此外,这里有一个实现链接,以供任何感兴趣的人参考。 - Seth Falco

9

在Java 8+中,您可以创建一个IntStream,范围是从0myArray.length,并使用类似以下代码检查相应(原始)数组中的所有值是否为true

return IntStream.range(0, myArray.length).allMatch(i -> myArray[i]);

这是这里唯一正确的答案之一(当然,除了被接受的答案)。大多数其他得到高赞的答案需要使用“Boolean []”数组才能工作,但问题明确指定了一个原始的“boolean []”数组。 - ThexXTURBOXx

2
boolean alltrue = true;
for(int i = 0; alltrue && i<booleanArray.length(); i++)
   alltrue &= booleanArray[i];

我认为这看起来很好,而且表现良好...


2
这可能并不更快,而且绝对不易读。为了寻求更加生动的解决方案…
int i = array.length()-1;
for(; i > -1 && array[i]; i--);
return i==-1

0

您可以通过将您的数组与其他布尔类型的数组比较,使用Arrays.equal方法来检查所有值项是真还是假,就像以下示例:

private boolean isCheckedAnswer(List<Answer> array) {
    boolean[] isSelectedChecks = new boolean[array.size()];
    for (int i = 0; i < array.size(); i++) {
        isSelectedChecks[i] = array.get(i).isChecked();
    }

    boolean[] isAllFalse = new boolean[array.size()];
    for (int i = 0; i < array.size(); i++) {
        isAllFalse[i] = false;
    }

    return !Arrays.equals(isSelectedChecks, isAllFalse);
}

虽然这可能是解决问题的另一种方式,但它似乎并不实用,因为它比两个得票最高的答案更复杂、更低效。 - Bernhard Barker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接