Can I cast collection to List?
Table of Contents
IntroductionI have written aboutJava streammethods extensively in the past. In this post, we will see six ways to convert a Java stream to a List. You can easily extend these if you want to convert a stream to a Set as well. 1 Collectors.toListThe first method is the most obvious and the easiest one. We use the Collectors class static methodtoList()to get a collector and pass it to thecollectmethod on the stream. This collector accumulates the stream elements into a new List. There are no guarantees on the type, the mutability, serializability or thread-safety of the list that is returned. It is animplementation detailthat it returns anArrayListtoday. It could change in the future. StreamPrints, [Jon, Adam, Perry, Monty]2 Collectors.toCollectionIf we wanted more control over the type of list we collect the stream elements into, we can useCollectors.toCollection method. This method accepts a Supplier of a Collection type as an argument. The returned collector accumulates the stream elements into the collection returned by the supplier (that we pass). For example, if we wanted the result list to be an ArrayList, we can pass a supplier as shown below Using method reference, we can rewrite the above as names = stream .collect(Collectors.toCollection(ArrayList::new));Similarly, if we wanted the result to be a LinkedList, we just change the supplier factory to create a new LinkedList instead. Hence, the result will be a LinkedList. Stream3 Collectors.toUnmodifiableListThe Collectors class has a static method calledtoUnmodifiableListwhich returns a Collector that accumulates the stream elements into anunmodifiable listas per the encounter order. Streamnull values not allowedUnlike the other Collector methods we have seen so far,toUnmodifiableListdoes not allow null values in the stream. It will throw a NullPointerException if there are null values in the stream. 4 forEachIn this rudimentary approach, we use forEach to iterate over the stream elements and add it to the result list. Hence, we pass the action to add to the list as a consumer. There are some problems when dealing with parallel stream pipelines.
ArrayList is not thread-safe but we are adding to it from multiple threads in the above code. Hence, we have to use a collection object that is thread-safe. 5 forEachOrderedTo overcome the problems in the previous method, we could use theforEachOrderedmethod. This method obeys the encounter order of a stream even for parallel streams (thus it can affect performance). As per Javadoc, Performing the action for one element happens-before performing the action for subsequent elements, but for any given element, the action may be performed in whatever thread the library chooses.Stream6 Convert to an Array and then to ListIn this option, we first convert the stream to an array through thetoArraymethod. ThetoArraymethod accepts a generator function to allocate the result array. StreamThe above shown generator function can also be written as size -> new String[size]. It takes an integer and allocates the result array of that size. Then, we callArrays.asListmethod passing the array to get back a List. The Arrays#asList method acts as a bridge between array-based and collection-based APIs. It returns a list which isbacked up by the passed array. Hence, changes made to the array will be visible in the list and vice-versa. Since it does not copy the array elements into a new list, the only additional thing is the call toasList. Mutability of the returned list by Arrays.asListThe returned list is modifiable (supportssetmethod). But it does not support adding to the list. Any changes to the array will be reflected in the list. But the array created from the stream was an intermediate object. No references to it is available after wrapping it in Arrays.asList in the above example. SummaryOptions 1, 2 and 3 are the recommended ways to convert a Java stream to a List. Options 4 and 5 (forEach and forEachOrdered) are not recommended due to the discussed limitations. Option 6 (converting a stream to array and then to a list) is a roundabout way. Generic method to convert stream to a ListYou can make a generic method to convert a stream to a List. Example: Option 1 can be written as a generic method as: private staticIn the same way you can turn any of the approaches we have seen into a generic method. Wherever you want to convert a stream to a list, you can call thecollectorsToListhelper method passing the list. However, this logic is not that huge that warrants it to be an utility method. ConclusionIn this post, we saw six ways to convert a Java Stream to a List. I recommend checking out the other posts on theJava stream. ReferencesWhy is list.parallelStream().forEach() not processing all the elements in the list in Java |