Issue
I know that once a Collection's stream actions of collect
/forEach
/min
/max
, the stream is closed and no longer valid for further function call.
My question is, how to avoid "duplicate stream operations" so that we can do different stream actions on same collection without duplicate computation?
E.g.
public static void main(String[] args) {
List<Integer> ls = new ArrayList<>(Arrays.asList( 11, 9, 7, 11, 24, 13, 37, 16 ));
Stream<Integer> s1 = ls.stream().filter(x -> x > 10).sorted().distinct().limit(4).skip(2);
s1.forEach(System.out::println);
// java.lang.IllegalStateException: stream has already been operated upon or closed
System.out.println(s1.max((x, y) -> x < y ? y : x).get()); // s1 is no longer useable.
}
Well, I know in order to get s1.max I have to construct the Stream again like :
Stream<Integer> sAnother = ls.stream().filter(x -> x > 10).sorted().distinct().limit(4).skip(2);
This works, but seems doing redundant work for the 2nd time. I hope that we can use this calling sequence, and make it executed once and only once:
filter(x -> x > 10).sorted().distinct().limit(4).skip(2)
and then: (1) Do the forEach to print elements. (2) Calculate the max element.
Not having to construct and compute the whole stream process twice.
Is there a way to achieve this? Thanks.
Solution
You should distinct() before sorting() to avoid to sort double values which you throw away anyway.
You could save your processed values in a collecten of your choice. I would recommend you a List (keep in mind that this List is unmodifiable) and if you need to work with streams from there, which i can't see from your code yet, then you could create new streams out of it. But i recommend you to do the following:
public static void main(String[] args) { List<Integer> ls = new ArrayList<>(Arrays.asList( 11, 9, 7, 11, 24, 13, 37, 16 )); List<Integer> s1 = ls.stream().filter(x -> x > 10).distinct().sorted().limit(4).skip(2).toList(); Integer max = null; for (Integer integer : s1) { if (max == null || integer.compareTo(max) > 0) { max = integer; } System.out.println(integer); } System.out.println(max); }
Answered By - xthe_white_lionx
Answer Checked By - David Marino (JavaFixing Volunteer)