Retrieving a List from a java.util.stream.Stream in Java 8
Solution 1
What you are doing may be the simplest way, provided your stream stays sequential—otherwise you will have to put a call to sequential() before forEach
.
[later edit: the reason the call to sequential() is necessary is that the code as it stands (forEach(targetLongList::add)
) would be racy if the stream was parallel. Even then, it will not achieve the effect intended, as forEach
is explicitly nondeterministic—even in a sequential stream the order of element processing is not guaranteed. You would have to use forEachOrdered
to ensure correct ordering. The intention of the Stream API designers is that you will use collector in this situation, as below.]
An alternative is
targetLongList = sourceLongList.stream()
.filter(l -> l > 100)
.collect(Collectors.toList());
Solution 2
Updated:
Another approach is to use Collectors.toList
:
targetLongList =
sourceLongList.stream().
filter(l -> l > 100).
collect(Collectors.toList());
Previous Solution:
Another approach is to use Collectors.toCollection
:
targetLongList =
sourceLongList.stream().
filter(l -> l > 100).
collect(Collectors.toCollection(ArrayList::new));
Solution 3
I like to use a util method that returns a collector for ArrayList
when that is what I want.
I think the solution using Collectors.toCollection(ArrayList::new)
is a little too noisy for such a common operation.
Example:
ArrayList<Long> result = sourceLongList.stream()
.filter(l -> l > 100)
.collect(toArrayList());
public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
return Collectors.toCollection(ArrayList::new);
}
With this answer I also want to demonstrate how simple it is to create and use custom collectors, which is very useful generally.
Solution 4
collect(Collectors.toList());
This is the call which you can use to convert any Stream to List.
more concretely:
List<String> myList = stream.collect(Collectors.toList());
from:
https://www.geeksforgeeks.org/collectors-tolist-method-in-java-with-examples/
Solution 5
There is a new method Stream.toList() in Java 16:
List<Long> targetLongList = sourceLongList
.stream()
.filter(l -> l > 100)
.toList();
Daniel K.
Updated on July 08, 2022Comments
-
Daniel K. almost 2 years
I was playing around with Java 8 lambdas to easily filter collections. But I did not find a concise way to retrieve the result as a new list within the same statement. Here is my most concise approach so far:
List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); List<Long> targetLongList = new ArrayList<>(); sourceLongList.stream().filter(l -> l > 100).forEach(targetLongList::add);
Examples on the net did not answer my question because they stop without generating a new result list. There must be a more concise way. I would have expected, that the
Stream
class has methods astoList()
,toSet()
, …Is there a way that the variables
targetLongList
can be directly be assigned by the third line? -
orbfish almost 9 yearsThis is, however, useful if you want a particular List implementation.
-
Eduard Korenschi over 8 yearsDespite beeing recommended to code against interfaces, there are clear cases (one of them being GWT) when you have to code against concrete implementations (unless you want all List implementations compiled and delivered as javascript).
-
Lii almost 8 yearsAddition: I think this codes gets a little shorter, clearer and prettier if you use a static import of
toList
. This is done by placing the following among the imports of the file:static import java.util.stream.Collectors.toList;
. Then the collect call reads just.collect(toList())
. -
Lii almost 8 yearsIn Eclipse it is possible to make the IDE add a static import for methods. This is done by adding the
Collectors
class in Preferences -> Java -> Editor -> Content Assist -> Favorites. After this, you only have to typetoLi
at hit Ctr+Space to have the IDE fill intoList
and add the static import. -
Daniel K. over 7 yearsI don't like that the collect() is only used to drive the stream so that the peek() hook is called on each item. The result of the terminal operation is discarded.
-
Lii over 7 yearsIt is very weird to call
collect
and then not save the return value. In that case you could useforEach
instead. But that is still a poor solution. -
Lluis Martinez about 7 yearsIf you declare result as List<Long> you don't need to use this util method. Collectors.toList will do. Also, using specific classes instead of interfaces is a code smell.
-
Lii about 7 years@LluisMartinez: "Collectors.toList will do.": No, not in many situations. Because it's not a good idea to use
toList
if you for example want to modify the list later in the program. ThetoList
documentation says this: "There are no guarantees on the type, mutability, serializability, or thread-safety of the List returned; if more control over the returned List is required, usetoCollection
.". My answer demonstrates a way to make it more convenient to do that in a common case. -
Lluis Martinez about 7 yearsIf you want to specifically create an ArrayList then it's ok.
-
Grzegorz Piwowarek almost 7 yearsUsing peek() in this way is an antipattern.
-
Mutant Bob over 6 yearsOne thing to keep in mind is that
IntStream
and some other almost-but-not-quite-Stream
s do not have thecollect(Collector)
method and you will have to callIntStream.boxed()
to convert them to a regularStream
first. Then again, maybe you just wanttoArray()
. -
Charles Wood over 6 yearsAnother pro for this method, from the
Collectors::toList
javadoc: "There are no guarantees on the type, mutability, serializability, or thread-safety of the List returned; if more control over the returned List is required, usetoCollection(Supplier)
." -
amarnath harish over 5 yearswhy we have to use
sequential()
beforeforEach
or use 'forEachOrdered` -
Maurice Naftalin over 5 years@amarnathharish Because forEach doesn't guarantee the order of operation execution for a parallel stream. The JavaDoc says "The behavior of this operation is explicitly nondeterministic. For parallel stream pipelines, this operation does not guarantee to respect the encounter order of the stream, as doing so would sacrifice the benefit of parallelism." (The first sentence of this quote actually means that order is not guaranteed for sequential streams either, although in practice it is preserved.)
-
Vaneet Kataria over 5 yearsAs per Stream Java docs peek method must be used for debugging purposes only .It should not be used for any processing other than debugging .
-
Vaneet Kataria over 5 yearsI don't find any toList method present in LongStream class. Could you run this code ?
-
user_3380739 over 5 years@VaneetKataria try
com.landawn.abacus.util.stream.LongStream
orLongStreamEx
in AbacusUtil -
B--rian almost 5 yearsThanks for your input. However, please explain what you changed and in how far it relates to the question.
-
Pratik Pawar almost 5 yearsHere firstly I converted my ArrayList to steam them using filter I filter out required data. Finally I have used collect method of java 8 stream to collect data in new list called as targetLongList.
-
Lei Yang almost 4 yearswhy cannot it be as simple as C# syntax:
(some ienumerable).ToList()
?