我正在尝试找到最快的方法,而不是通过Java SE 8 Streams进行联合/排除/交叉操作的复杂方法。
我这样做:
Stream<String> fruitStream = Stream.of("apple", "banana", "pear", "kiwi", "orange");
Stream<String> fruitStream2 = Stream.of("orange", "kiwi", "melon", "apple", "watermelon");
//Trying to create exclude operation
fruitStream.filter(
item -> !fruitStream2.anyMatch(item2 -> item2.equals(item)))
.forEach(System.out::println);
// Expected result: fruitStream - fruitStream2: ["banana","pear"]
我得到以下例外:
java.lang.IllegalStateException:stream已经被操作或关闭
如果我能够做这个操作,我可以开发自己所有其余的,联合,交叉等......
所以,2点是:
1)我在这个解决方案中做错了什么?
2)是否有一种不太复杂的方法在两个流之间执行操作?
注意
我想用流来了解它们。不想将它们转换为数组或列表
答案 0 :(得分:6)
第一次执行item -> !fruitStream2.anyMatch(item2 -> item2.equals(item))
时,它会消耗fruitStream2
。无法再次使用fruitStream2
来过滤fruitStream1
中的第二项。
为什么不创建Set
并使用contains
,而不是使用第二个流?
Set<String> otherFruits = new HashSet<>(); // Add the fruits.
fruitStream.filter(f -> !otherFruits.contains(f)).forEach(System.out::println);
答案 1 :(得分:4)
我在这个解决方案中做错了什么?
您不能使用相同Stream
的多次消费,并且在此消耗fruitStream2
的次数与fruitStream
是否有一种不太复杂的方法在两个流之间执行操作?
您可以将第二个Stream
转换为Set
:
Stream<String> fruitStream = Stream.of("apple", "banana", "pear", "kiwi", "orange");
Set<String> fruitSet = Stream.of("orange", "kiwi", "melon", "apple", "watermelon")
.collect(Collectors.toSet());
fruitStream.filter(item -> !fruitSet.contains(item)).forEach(System.out::println);
<强>输出:强>
banana
pear
答案 2 :(得分:1)
Stream是仅执行一次的内部迭代/处理。这是一个非常有限的领域。
Supplier<Stream<String>> fruitStream2S = () ->
Stream.of("orange", "kiwi", "melon", "apple", "watermelon");
fruitStream.filter(item -> !fruitStream2s.get().anyMatch(item2 -> item2.equals(item)))
.forEach(System.out::println);
效率不高。
答案 3 :(得分:0)
这有点愚蠢,它不会给你带来很好的性能,但它确实满足了你不需要(explicitly)创建数组或列表的要求:
public static void main(String[] args) {
new Object() {
Stream<String> fruitStream = Stream.of("apple", "banana", "pear", "kiwi", "orange");
Stream<String> fruitStream2 = Stream.of("orange", "kiwi", "melon", "apple", "watermelon");
{
fruitStream2.forEach(f -> fruitStream = fruitStream.filter(Predicate.isEqual(f).negate()));
fruitStream.forEach(System.out::println);
}
};
}
输出:
banana
pear
编辑一种(稍微)更简单的方法:
public static void main(String[] args) {
Stream<String> fruitStream = Stream.of("apple", "banana", "pear", "kiwi", "orange");
Stream.of("orange", "kiwi", "melon", "apple", "watermelon")
.map(Predicate::isEqual)
.reduce(Predicate::or)
.map(Predicate::negate)
.map(fruitStream::filter)
.orElse(fruitStream)
.forEach(System.out::println);
}