Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Operations between java Streams

I am trying to find the fastest way, and less complex way to do some union/exclude/intersection operations over Java SE 8 Streams.

I am doing this:

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"]

I get the following Exception:

java.lang.IllegalStateException: stream has already been operated upon or closed

If I was able to do this operation, I could develope myself all the rest, union, intersection etc...

So, the 2 points are:

1) What am I doing wrong in this solution to get that Exception?

2) Is there a less complex way to perform operations between 2 streams?

Note

I want to use streams to learn about them. Dont want to transform them into arrays or lists

like image 781
Mayday Avatar asked Dec 19 '22 13:12

Mayday


2 Answers

The first time item -> !fruitStream2.anyMatch(item2 -> item2.equals(item)) executes, it consumes fruitStream2. fruitStream2 can not be used again to filter the second item in fruitStream1.

Rather than using a second stream, why not create a Set and use contains?

Set<String> otherFruits = new HashSet<>(); // Add the fruits.
fruitStream.filter(f -> !otherFruits.contains(f)).forEach(System.out::println);
like image 70
bradimus Avatar answered Jan 04 '23 03:01

bradimus


What am I doing wrong in this solution to get that Exception?

You cannot consume several times the same Stream and here you consume fruitStream2 as many times as you have elements in fruitStream

Is there a less complex way to perform operations between 2 streams?

You could convert the second Stream as a 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);

Output:

banana
pear
like image 41
Nicolas Filotto Avatar answered Jan 04 '23 01:01

Nicolas Filotto