检查布尔数组中的所有值是不是为真的最优雅方法是啥?
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];
检查所有值是否为真的最优雅的方法是什么?
【问题讨论】:
如果你真的需要一种快速的方法来做到这一点,那么你最好将你的标志存储在 int 或 long (甚至是 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+ 中,您可以在 0
到 myArray.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 -> 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这可能不会更快,而且绝对不是很可读。所以,为了丰富多彩的解决方案......
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 个值)以上是关于检查布尔数组中的所有值是不是为真的最优雅方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章