检查布尔数组中的所有值是不是为真的最优雅方法是啥?

Posted

技术标签:

【中文标题】检查布尔数组中的所有值是不是为真的最优雅方法是啥?【英文标题】:What is the most elegant way to check if all values in a boolean array are true?检查布尔数组中的所有值是否为真的最优雅方法是什么? 【发布时间】:2012-01-05 20:21:41 【问题描述】:

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

boolean[] myArray = new boolean[10];

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

【问题讨论】:

如果你真的需要一种快速的方法来做到这一点,那么你最好将你的标志存储在 intlong (甚至是 long[])并自己做“数学”。然后您可以一次检查多达 32 或 64 个值。但是,我怀疑您的那个特定位置会成为瓶颈。 @donturner 你的意思是最快的计算速度,还是快速的编写速度(更少的代码)? 非常感谢您的快速回复。我的意思是“最快的编写”,而不是执行。也许我应该说“最优雅”。 循环并在没有时中断。为了速度,最好使用整数或哈希图。 【参考方案1】:

只需使用Arrays.toString 将数组转换为String 并测试它是否包含false

演示:

import java.util.Arrays;

public class Main 
    public static void main(String args[]) 
        // Test
        System.out.println(areAllValuesTrue(new boolean[]  true, true, true, true ));
        System.out.println(areAllValuesTrue(new boolean[]  true, false, false, true ));
        System.out.println(areAllValuesTrue(new boolean[]  false, false, false, false ));
    

    static boolean areAllValuesTrue(boolean[] arr) 
        return !Arrays.toString(arr).contains("false");
    

输出:

true
false
false

【讨论】:

【参考方案2】:

我不敢相信没有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);

【讨论】:

我认为使用 BitSet 是个好主意。然而,需要注意比较基数(计算设置为真的位)和长度(计算所有位置,真假,直到最后一个设置为真)。我遇到了比较与具有尾随错误的 ListArray 相关的 BitSet 的长度 - 也就是说,我需要 ListArray 长度而不是 BitSet 长度。 这就是为什么你应该使用 .size() 而不是 .length() 我不敢相信没有 Apache Commons 解决方案。哦,等等,现在there is one。 ;) @MarkRenouf 再次查看 Doc 并进行一些测试,KTys 是对的。例如在我的 java 设置中,.size() 无论 n (... BitSet(n)) 都返回 64。 !!!不好的建议:当上下文正常时,有人可以使用 .length() 确保最后一个值是真的并且永远不会改变。【参考方案3】:

那一行应该足够了:

BooleanUtils.and(boolean... array)

但要让只看链接的纯粹主义者平静下来:

对一组布尔值执行和。

【讨论】:

【参考方案4】:

在 Java 8+ 中,您可以在 0myArray.length 的范围内创建一个 IntStream,并检查相应(原始)数组中的所有值是否为 true,例如,

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

【讨论】:

这是这里唯一正确的答案之一(当然在接受的答案旁边)。大多数其他高度赞成的答案需要Boolean[] 数组才能工作,但问题明确指定了一个原始boolean[] 数组。【参考方案5】:

您可以通过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);

【讨论】:

虽然这可能是解决问题的另一种方法,但它似乎并不真正有用,因为它不如两个投票最多的答案简单且效率低。【参考方案6】:

在 Java 8 中,您可以这样做:

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

甚至更短:

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

注意: 您需要 Boolean[] 才能使此解决方案起作用。因为你不能有一个原始列表。

【讨论】:

Arrays.asList(myArray).stream().allMatch(Boolean::booleanValue) 将适用于所有true 和所有false Arrays.asList(myArray).stream().allMatch(val -&gt; Boolean.TRUE.equals(val)); 如果数组中有空值,这也将正确处理。【参考方案7】:
boolean alltrue = true;
for(int i = 0; alltrue && i<booleanArray.length(); i++)
   alltrue &= booleanArray[i];

我认为这看起来不错并且表现良好...

【讨论】:

【参考方案8】:

这取决于您想要查找此信息的次数(如果不止一次):

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 @CarlosHeuberger 一个好地方,最近一直在 C#ing,把我的布尔值和布尔值弄混了! @CarlosHeuberger 等待每个应该比一个简单的循环更快?如果 JIT 可以内联所有内容并进行相应优化,则迭代器解决方案可能与直接访问一样快,但肯定不会更快(另一方面,数组长度上的 CSE 几乎肯定会发生)。理论上从 length() - 1 开始并在 0 处停止在 x86 上可能会稍微快一些,但这甚至不再是微优化了。 -1 因为上面的例子没有编译:unexpected type required: reference found: boolean @AmirPashazadeh 最初的问题是“最快的方式...”,而不是“最优雅的方式...”。是的,创建会更慢,但是 HashSet 中的查找是 O(1) 而在 ArrayList 中它们是 O(n),因此我声明了 OP 希望查找此信息的次数。由于 java 缺少具体化的泛型,因此在 contains 方法中对布尔值进行装箱的成本可能也值得一提,但是在任何最近的 JVM 上,这将形成 gen 0 收藏品,并且成本应该可以忽略不计。也可以通过传递 Boolean.False 来缓解这种情况。【参考方案9】:
public static boolean areAllTrue(boolean[] array)

    for(boolean b : array) if(!b) return false;
    return true;

【讨论】:

这可能是个人喜好,但我会使用isAllTrue(boolean... array),以防将来该方法需要或需要其他输入。它仍然接受数组,但我们不想限制未来可能的用户。【参考方案10】:
Arrays.asList(myArray).contains(false)

【讨论】:

一行,清晰,简洁,O(n) 查找,这里有什么不喜欢的? 只有当它是 Boolean[] 而不是 boolean[] 时才有效。因为你不能有一个带有原语的 List,你最终会得到一个 Arrays.asList(boolean[]) 和一个 List 永远不包含 false 因为它总是包含数组。 @DavidGeorgReichelt 我认为这不是提问者的主要关注点。它明确指出。来自布尔数组。所以... @acorello 啊我现在明白了,谢谢你的解释。我删除了我原来的评论:) @Samir 没问题,因为您已经删除了最初的评论,所以我决定删除我的回复,因为没有这些评论就没有意义,而且我不希望 SO 看起来令人困惑......这个评论将在 24 小时内自毁。 ;)【参考方案11】:

这可能不会更快,而且绝对不是很可读。所以,为了丰富多彩的解决方案......

int i = array.length()-1;
for(; i > -1 && array[i]; i--);
return i==-1

【讨论】:

【参考方案12】:

好的。这是我能想到的“最优雅”的解决方案:

boolean allTrue = !Arrays.toString(myArray).contains("f");

希望有帮助!

【讨论】:

“优雅”?我认为不是......它可能是一行,但不是检查每个 8 位的 n 值(知道内存中数组中 boolean 的大小),而是检查这些的字符串表示,这将可以从(n * 4) + 2 + ((n-1) * 2)(n * 5) + 2 + ((n-1) * 2) 的任何位置取值,每个值都是32 位,知道Arrays.toString 方法的工作原理以及内存中char 的一侧。 (对于这个特定的例子,这是 60 到 70 个值)

以上是关于检查布尔数组中的所有值是不是为真的最优雅方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

检查数组中的所有值是不是为真,然后返回一个真布尔语句(javascript)[重复]

如果不为空,检查查询字符串参数值的最优雅方法是啥?

使用 PHP 检查多个值是不是为整数的最简单方法是啥?

检查至少十分之二的布尔值是真的

查找值为真的布尔数组的索引

布尔列表检查列表中的每个项目是不是为假