java8 stream不会更改类成员

时间:2016-10-11 10:03:24

标签: java java-8 java-stream

我有这段代码:

Set<String> namesSet = new HashSet<>();

@Override
public boolean isValid(List<String> input) {
    input.stream().map(item -> namesSet.add(item));
    return namesSet.size() == input.size();
}

input是一个包含一个项目的列表。

为什么在stream::map之后没有将此项添加到namesSet?

更新这是我的修复:

Set<String> namesSet;

@Override
public boolean isValid(List<String> input) {
    namesSet = new HashSet<>();
    input.stream().forEach(item -> namesSet.add(item));
    return namesSet.size() == input.size();
}

3 个答案:

答案 0 :(得分:6)

流操作是惰性的,除非您关闭forEachcollect等终端操作,否则不会执行。

在这种情况下,请使用forEach代替mapmap是一个中间操作。

顺便说一句,你的isValid方法会修改字段,这听起来非常令人讨厌。如果您拨打一次并获得true,则在第二次通话时,您将获得false。无论如何,我不太明白这个方法 - 因为(一旦你修复它),它将始终在第一次调用时返回true并在所有后续调用中返回false。唯一的例外是空列表,在这种情况下,它将始终返回true

修改

仔细查看您的方法,如果您只想查找列表是否包含重复项,您可以这样做:

input.stream().distinct().count() == input.size()

答案 1 :(得分:2)

要解决您的问题,不需要使用Stream API。

只需使用Set的内容创建List(使用HashSet s copy constructor )并比较尺寸:

@Override
public boolean isValid(List<String> input) {
    Set<String> namesSet = new HashSet<>(input); // copies the content of 'input'
    return namesSet.size() == input.size();
}

答案 2 :(得分:0)

来自here

“中间操作返回一个新流。它们总是很懒惰;执行像filter()这样的中间操作实际上并不执行任何过滤,而是创建一个新流,当遍历时,它包含初始流的元素与给定谓词匹配。在执行管道的终端操作之前,管道源的遍历不会开始。“

所以你需要调用终端操作。