'Collect both matching and non-matching in one stream processing?
Is there a way to collect both matching and not matching elements of stream in one processing? Take this example:
final List<Integer> numbers = Arrays.asList( 1, 2, 3, 4, 5 );
final List<Integer> even = numbers.stream().filter( n -> n % 2 == 0 ).collect( Collectors.toList() );
final List<Integer> odd = numbers.stream().filter( n -> n % 2 != 0 ).collect( Collectors.toList() );
Is there a way to avoid running through the list of numbers twice? Something like "collector for matches and collector for no-matches"?
Solution 1:[1]
You may do it like so,
final Map<Boolean, List<Integer>> parityMap = numbers.stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0));
final List<Integer> even = parityMap.get(true);
final List<Integer> odd = parityMap.get(false);
Solution 2:[2]
If you have more than 2 groups (instead of odd and even here using %2) for example to group ints in remainder classes %3 you can use a Function:
Function<Integer, Integer> fun = i -> i%3;
List<Integer> a = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Map<Integer, List<Integer>> collect = a.stream().collect(Collectors.groupingBy(fun));
System.out.println(collect);
//{0=[3, 6, 9], 1=[1, 4, 7, 10], 2=[2, 5, 8]}
Or imagine you have a list of strings which you want to group by starting char instead of grouping matching and non-matching (for e.g. starts with a or not) you could do something like :
Function<String, Character> fun = s -> s.charAt(0);
List<String> a = Arrays.asList("baz","buzz","azz","ayy","foo","doo");
Map<Character, List<String>> collect = a.stream().collect(Collectors.groupingBy(fun));
System.out.println(collect);
//{a=[azz, ayy], b=[baz, buzz], d=[doo], f=[foo]}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |