Sunday, March 19, 2017

5 ways to Convert Java 8 Stream to List - Example, Tutorial

One of the common problem while working with Stream API in Java 8 is how to convert a Stream to List in Java because there is no toList() method present in Stream class. When you are processing a List using Stream's map and filter method, you ideally want your result in some collection so that you can pass it to other part of program. Though class has toArray() method to convert Stream to Array, but  there is no similar method to convert Stream to List or Set. Java has a design philosophy of providing conversion method between new and old API classes e.g. when they introduced Path class in JDK 7, which is similar to, they provided a toPath() method to File class. Similarly they could have provided convenient methods like toList(), toSet() into Stream class, but unfortunately they have not done that. Anyway, It seems they did thought about this and provided a class called Collector to collect the result of stream operations into different container or Collection classes. Here you will find methods like toList(), which can be used to convert Java 8 Stream to List. You can also use any List implementation class e.g. ArrayList or LinkedList to get contents of that Stream. I would have preferred having those method at-least the common ones directly into Stream but nevertheless there is something you can use to convert a Java 8 Stream to List. BTW, my research to this task also reveals several other way to achieve the same result, which I have summarized in this tutorial. If would suggest to prefer standard way, which is by using Stream.collect() and Collectors class, but its good to know other ways, just in case if you need.

Java 8 Stream to List conversion - 5 examples

Here are 5 simple ways to convert a Stream in Java 8 to List e.g. converting a Stream of String to a List of String, or converting a Stream of Integer to List of Integer and so on.

Using Collectors.toList() method
This is the standard way to collect the result of stream in a container e.g. List, Set or any Collection. Stream class has a collect() method which accepts a Collector and you can use Collectors.toList() method to collect the result in a List.

List listOfStream = streamOfString.collect(Collectors.toList());

Using Collectors.toCollection() method
This is actually generalization of previous method, here instead of creating List, you can collect elements of Stream in any Collection, including ArrayList, LinkedList or any other List. In this example, we are collecting Stream elements into ArrayList.  The toColection() method returns a Collector that accumulates the input elements into a new Collection, in encounter order. The Collection is created by the provided Supplier instance, in this case we are using ArrayList::new, a constructor reference to collect them into ArrayList. You can also use lambda expression in place of method reference here, but method reference results in much more readable and concise code.

List listOfString  = streamOfString.collect(Collectors.toCollection(ArrayList::new));

Using forEach() method
You can also sue forEach() method to go through all element of Stream one by one and add them into a new List or ArrayList. This is simple, pragmatic approach, which beginners can use to learn.

Stream streamOfLetters = Stream.of("abc", "cde",
                "efg", "jkd", "res");
ArrayList list = new ArrayList<>();

Using forEachOrdered method
This is extension of previous example, if Stream is parallel then elements may be processed out of order but if you want to add them into the same order they were present in Stream, you can use forEachOrdered() method. If you are not comfortable with forEach, I suggest look at this Stream tutorial to understand more.

Stream streamOfNumbers = Stream.of("one", "two",
                "three", "four", "five");
ArrayList myList = new ArrayList<>();

Using toArray() method
Stream provides direct method to convert Stream to array, toArray(). The method which accepts no argument returns an object array as shown in our our sample program, but you can still get which type of array you want by using overloaded version of that method. Just like we have done in following example to create String array :

Stream streamOfShapes = Stream.of("Rectangle", "Square", "Circle", "Oval");
String[] arrayOfShapes = streamOfShapes.toArray(String[]::new);
List listOfShapes = Arrays.asList(arrayOfShapes);

Sample Program to convert Stream to List in Java 8

Java 8 Stream to List ExampleHere is the complete Java program to demonstrate all these five methods of converting Java 8 Streams to List. You can directly run them if you have installed JDK 8 in your machine. BTW, You should be using Netbeans with JDK 8 to code, compile and run Java program. The IDE has got excellent support and will help you to learn Java 8 quickly.

package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

 * Java Program to convert Stream to List in Java 8
 * @author Javin Paul
public class Java8StreamToList{

    public static void main(String args[]) throws IOException {
        Stream<String> streamOfString = Stream.of("Java", "C++",
                "JavaScript", "Scala", "Python");

        // converting Stream to List using Collectors.toList() method
        streamOfString = Stream.of("code", "logic",
                "program", "review", "skill");
        List<String> listOfStream = streamOfString.collect(Collectors.toList());
        System.out.println("Java 8 Stream to List, 1st example : " + listOfStream);

        // Java 8 Stream to ArrayList using Collectors.toCollection method
        streamOfString = Stream.of("one", "two",
                "three", "four", "five");
        listOfStream = streamOfString.collect(Collectors.toCollection(ArrayList::new));
        System.out.println("Java 8 Stream to List, 2nd Way : " + listOfStream);

        // 3rd way to convert Stream to List in Java 8
        streamOfString = Stream.of("abc", "cde",
                "efg", "jkd", "res");
        ArrayList<String> list = new ArrayList<>();
        System.out.println("Java 8 Stream to List, 3rd Way : " + list);

        // 4th way to convert Parallel Stream to List
        streamOfString = Stream.of("one", "two",
                "three", "four", "five");
        ArrayList<String> myList = new ArrayList<>();
        System.out.println("Java 8 Stream to List, 4th Way : " + myList);
        // 5th way of creating List from Stream in Java
        // but unfortunately this creates array of Objects
        // as opposed to array of String
        Stream<String> streamOfNames = Stream.of("James", "Jarry", "Jasmine", "Janeth");
        Object[] arrayOfString = streamOfNames.toArray();
        List<Object> listOfNames = Arrays.asList(arrayOfString);
        System.out.println("5th example of Stream to List in Java 8 : " + listOfNames);

        // can we convert the above method to String[] instead of 
        // Object[], yes by using overloaded version of toArray()
        // as shown below :
        Stream<String> streamOfShapes = Stream.of("Rectangle", "Square", "Circle", "Oval");
        String[] arrayOfShapes = streamOfShapes.toArray(String[]::new);
        List<String> listOfShapes = Arrays.asList(arrayOfShapes);
        System.out.println("modified version of last example : " + listOfShapes);



Output :
Java 8 Stream to List, 1st example : [code, logic, program, review, skill]
Java 8 Stream to List, 2nd Way : [one, two, three, four, five]
Java 8 Stream to List, 3rd Way : [abc, cde, efg, jkd, res]
Java 8 Stream to List, 4th Way : [one, two, three, four, five]
5th example of Stream to List in Java 8 : [James, Jarry, Jasmine, Janeth]
modified version of last example : [Rectangle, Square, Circle, Oval]

That's all about how to convert Stream to List in Java 8. You have seen there are several ways to perform the conversion but I would suggest you stick with standard approach i.e. by using Stream.collect(Collectors.toList()) method.

Further Learning
The Complete Java MasterClass
From Collections to Streams in Java 8
Refactoring to Java 8 Streams and Lambdas Self- Study Workshop

If you like this Java 8 tutorial and hungry for more, check out following Java 8 tutorials about lambda expression, Stream API, default methods and Date Time API :
  • Java 8 - 20 Date and Time Examples for beginners (see tutorial)
  • 5 FREE Java 8 tutorials and Books (resources)
  • How to Read File in Java 8 in one line? (example)
  • Simple Java 8 Comparator Example (example)
  • Top 10 tutorials to Learn Java 8 (tutorial)
  • How to use Map function in Java 8 (example)
  • Thinking of Java 8 Certification? (read more)
  • How to read/write RandomAccessFile in Java? (solution)
  • How to use Lambda Expression in Place of Anonymous class (solution)
  • 10 Examples of Stream API in Java (examples)
  • How to filter Collection in Java 8 using Predicates? (solution)
  • How to use Default method in Java 8. (see here)
  • 10 Java 7 Feature to revisit before you starts with Java 8 (read more)


Anonymous said...

When you get a list from Stream, does it also preserve the order of elements as they were in Stream? Same question is what if we get a Set from Stream and than convert it to list? Also, how can we get ArrayList or LinkedList or Vector from Stream?

javin paul said...

@Anonymous, if Stream is not parallel then yes it preserve the stream order but with parallel stream there is no guarantee, because elements are traversed in arbitrary order.

If you get Set the order is already lost, you won't get order back by converting to list.

Yes, you can get ArrayList from Stream by using Collectors.toCollection(ArrayList::new) method. Similarly you can collect stream elements into LinkedList and Vector.

Post a Comment