Reputation: 119
Consider I have a list with two types of data,one valid and the other invalid.
If I starting filter through this list, can i collect two lists at the end?
Upvotes: 10
Views: 20000
Reputation: 14317
One way using Java 8 streams API is to use the Collectors.partitioningBy
collector.
Consider I have a List
of String
elements: the input list has strings with various lengths; only strings with length 3 are valid.
List<String> input = Arrays.asList("one", "two", "three", "four", "five");
Map<Boolean, List<String>> map =
input.collect(Collectors.partitioningBy(s -> s.length() == 3));
System.out.println(map); // {false=[three, four, five], true=[one, two]}
List<String> valid = map.get(true); // [one, two]
List<String> invalid = map.get(false); // [three, four, five]
The resulting Map
has only two records; one with valid and the other with not-valid input list elements. The map record with key=true
has the valid string as a List
: one, two. The other is a key=false
and the not-valid strings: three, four, five.
Note that Collectors.partitioningBy
produces always two records in the resulting map irrespective of the existence of valid or not-valid values.
Upvotes: 8
Reputation: 183
If you need to classify binary (true|false), you can use Collectors.partitioningBy that will return Map<Boolean, List> (or other downstream collection like Set, if you additionally specify).
If you need more than 2 categories - use groupBy or just Collectors.toMap of collections.
Upvotes: 1
Reputation: 140613
The collector can only return a single object!
But you could create a custom collector that simply puts the stream elements into two lists, to then return a list of lists containing these two lists.
There are many examples how to do that.
Upvotes: 2
Reputation: 131516
Can we collect two lists from Java 8 streams?
You cannot but if you have a way to group elements of the List
s according to a condition.
In this case you could for example use Collectors.groupingBy()
that will return Map<Foo, List<Bar>>
where the values of the Map
are the two List.
Note that in your case you don't need stream to do only filter.
Filter the invalid list with removeIf()
and add all element of that in the first list :
invalidList.removeIf(o -> conditionToRemove);
goodList.addAll(invalidList);
If you don't want to change the state of goodList
you can do a shallow copy of that :
invalidList.removeIf(o -> conditionToRemove);
List<Foo> terminalList = new ArrayList<>(goodList);
terminalList.addAll(invalidList);
Upvotes: 9
Reputation: 719551
Another suggestion: filter using a lambda
that adds the elements that you want to filter out of the stream to a separate list.
Upvotes: 2