我有这段代码:
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();
}
答案 0 :(得分:6)
流操作是惰性的,除非您关闭forEach
或collect
等终端操作,否则不会执行。
在这种情况下,请使用forEach
代替map
。 map
是一个中间操作。
顺便说一句,你的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()这样的中间操作实际上并不执行任何过滤,而是创建一个新流,当遍历时,它包含初始流的元素与给定谓词匹配。在执行管道的终端操作之前,管道源的遍历不会开始。“
所以你需要调用终端操作。