hen*_*xin 12 java arrays lambda java-8 java-stream
假设我有一个庞大的 Boolean数组flags:
Boolean[] flags = { true, false, true }; // 3 means "many"
Run Code Online (Sandbox Code Playgroud)
我想做两件事flags:
true返回并返回指标;false.使用Java 8的lambda表达式,我可以按如下方式执行:
indicator = Arrays.stream(flags).allMatch(flag -> flag);
Arrays.stream(flags).forEach(flag -> flag = false);
return indicator;
Run Code Online (Sandbox Code Playgroud)
但是,此实现扫描flags两次.由于flags是巨大的,我不希望这样.另外,我更喜欢lambda方式.有没有办法checkIfAllTrueAndReset用(单行)lambda表达式实现这种语义,flags只扫描一次?
相关但不相同:检查布尔数组中的所有值是否为真的最优雅的方法是什么?
注意:我从评论和答案中学到了很多东西.谢谢你们!
Stream很酷,但不是这个.BitSet(以及它的位原子对应物AtomicBitSet)更适合这种情况(因此被接受为答案;感谢其他人).map(Stream或通常是函数式编程)的副作用.Arrays.stream(flags).forEach(flag -> flag = false)(在我的代码中)没有设置任何东西!这对于流和lambdas来说是一个糟糕的匹配,并没有很好的方法来做到这一点.
问题是,蒸汽使用集合的元素,但您需要修改实际的集合.
我认为你最好使用旧式for循环.
一个不太好的解决方案是在数组的索引上获取流,并使用其中的一个forEach循环遍历数组.一个AtomicBoolean可用于存储在所有元素都是true.这可以并行运行,但我认为普通的for循环更好.
例:
Boolean[] flags = { true, true, true };
AtomicBoolean allTrue = new AtomicBoolean(true);
IntStream.range(0, flags.length)
.forEach(ix -> {
if (!flags[ix]) allTrue.set(false);
flags[ix] = false;
});
Run Code Online (Sandbox Code Playgroud)
在该问题的评论中,有人提到它可能是一个有趣的解决方案AtomicBoolean.在这种情况下,可以使用具有流的解决方案,因为可以在不修改原始集合的情况下重置元素.
然而,解决方案确实有问题,所以最好不要使用它.问题是map用于副作用(重置值)和映射操作(提取旧值).我认为可以并行运行它,但它可能比正常的for循环慢,因为每个元素的操作都很小.
另请注意,allMatch由于该操作是短路的,因此无法使用,如果发现false它将终止,后续元素将不会被重置.
AtomicBoolean[] flags = { new AtomicBoolean(true), new AtomicBoolean(false), new AtomicBoolean(true) };
boolean allTrue = Stream.of(flags)
.map(b -> b.getAndSet(false))
.reduce(true, (a, b) -> a && b);
Run Code Online (Sandbox Code Playgroud)
如果你真的想用一行中的流做这个,那么你可以做这样的事情
boolean allTrue = IntStream.range(0, flags.length).reduce(0,
(result, i) -> flags[i] ^ (flags[i] = false) ? result : 1) == 0;
Run Code Online (Sandbox Code Playgroud)
然而,这看起来并不是一个好主意,我倾向于使用BitSet@MarounMaroun建议的
| 归档时间: |
|
| 查看次数: |
2763 次 |
| 最近记录: |