I'm looking for the most pain free way to filter a collection. I'm thinking something like
Collection<?> foo = existingCollection.stream().filter( ... ). ...
But I'm not sure how is best to go from the filter, to returning or populating another collection. Most examples seem to be like "and here you can print". Possible there's a constructor, or output method that I'm missing.
Differences between a Stream and a Collection: A stream does not store data. An operation on a stream does not modify its source, but simply produces a result. Collections have a finite size, but streams do not.
Stream to Collection using Collectors. toCollection() You can also collect or accumulate the result of Stream processing into a Collection of your choices like ArrayList, HashSet, or LinkedList. There is also a toCollection() method in the Collectors class that allows you to convert Stream to any collection.
Streams are not modifiable i.e one can't add or remove elements from streams. These are modifiable i.e one can easily add to or remove elements from collections. Streams are iterated internally by just mentioning the operations. Collections are iterated externally using loops.
There’s a reason why most examples avoid storing the result into a Collection
. It’s not the recommended way of programming. You already have a Collection
, the one providing the source data and collections are of no use on its own. You want to perform certain operations on it so the ideal case is to perform the operation using the stream and skip storing the data in an intermediate Collection
. This is what most examples try to suggest.
Of course, there are a lot of existing APIs working with Collection
s and there always will be. So the Stream
API offers different ways to handle the demand for a Collection
.
Get an unmodifiable List
implementation containing all elements (JDK 16):
List<T> results = l.stream().filter(…).toList();
Get an arbitrary List
implementation holding the result:
List<T> results = l.stream().filter(…).collect(Collectors.toList());
Get an unmodifiable List
forbidding null
like List.of(…)
(JDK 10):
List<T> results = l.stream().filter(…).collect(Collectors.toUnmodifiableList());
Get an arbitrary Set
implementation holding the result:
Set<T> results = l.stream().filter(…).collect(Collectors.toSet());
Get a specific Collection
:
ArrayList<T> results = l.stream().filter(…).collect(Collectors.toCollection(ArrayList::new));
Add to an existing Collection
:
l.stream().filter(…).forEach(existing::add);
Create an array:
String[] array=l.stream().filter(…).toArray(String[]::new);
Use the array to create a list with a specific specific behavior (mutable, fixed size):
List<String> al=Arrays.asList(l.stream().filter(…).toArray(String[]::new));
Allow a parallel capable stream to add to temporary local lists and join them afterward:
List<T> results = l.stream().filter(…).collect(ArrayList::new, List::add, List::addAll);
(Note: this is closely related to how Collectors.toList()
is currently implemented, but that’s an implementation detail, i.e. there is no guarantee that future implementations of the toList()
collectors will still return an ArrayList
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With