当前位置:  开发笔记 > 编程语言 > 正文

检查是否全部为true并使用Java 8的单行lambda表达式重置Boolean []数组

如何解决《检查是否全部为true并使用Java8的单行lambda表达式重置Boolean[]数组》经验,为你挑选了3个好方法。

假设我有一个庞大的 Boolean数组flags:

Boolean[] flags = { true, false, true };    // 3 means "many"

我想做两件事flags:

检查所有元素是否都true返回并返回指标;

将所有元素重置为false.

使用Java 8的lambda表达式,我可以按如下方式执行:

indicator = Arrays.stream(flags).allMatch(flag -> flag);
Arrays.stream(flags).forEach(flag -> flag = false);
return indicator;

但是,此实现扫描flags两次.由于flags是巨大的,我不希望这样.另外,我更喜欢lambda方式.有没有办法checkIfAllTrueAndReset用(单行)lambda表达式实现这种语义,flags只扫描一次?


相关但不相同:检查布尔数组中的所有值是否为真的最优雅的方法是什么?


注意:我从评论和答案中学到了很多东西.谢谢你们!

    Stream很酷,但不是这个.

    BitSet(以及它的位原子对应物AtomicBitSet)更适合这种情况(因此被接受为答案;感谢其他人).

    不鼓励map(Stream或通常是函数式编程)的副作用.

    Arrays.stream(flags).forEach(flag -> flag = false)(在我的代码中)没有设置任何东西!

Maroun.. 16

使用BitSet该类的经典示例:

该类实现了一个根据需要增长的位向量.位组的每个组件都有一个布尔值.

在复杂性方面,BitSet每个boolean值使用~1位,这比使用大型Boolean对象更好.

关于是否设置所有位的检查(真或假),API提供了许多有用的方法 - 并且它们非常有效.



1> Maroun..:

使用BitSet该类的经典示例:

该类实现了一个根据需要增长的位向量.位组的每个组件都有一个布尔值.

在复杂性方面,BitSet每个boolean值使用~1位,这比使用大型Boolean对象更好.

关于是否设置所有位的检查(真或假),API提供了许多有用的方法 - 并且它们非常有效.



2> Lii..:

对于流和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;
    });

原子布尔的解决方案

在该问题的评论中,有人提到它可能是一个有趣的解决方案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);


@FedericoPeraltaSchaffner:当然!那要好多了,谢谢!
@hengxin:*"我在地图中修改了原始集合的次数"*这并不是绝对禁止的,但它违背了流库的功能性思想.[map`]的文档(https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#map-java.util.function.Function-)说操作应该是*[非干扰*](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#NonInterference)和[*stateless*] (https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#Statelessness).

3> SamYonnou..:

如果你真的想用一行中的流做这个,那么你可以做这样的事情

boolean allTrue = IntStream.range(0, flags.length).reduce(0,
    (result, i) -> flags[i] ^ (flags[i] = false) ? result : 1) == 0;

然而,这看起来并不是一个好主意,我倾向于使用BitSet@MarounMaroun建议的

推荐阅读
雯颜哥_135
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有