Java 8 - Stream.collect() Example

The collect() method of Stream class can be used to accumulate elements of any Stream into a Collection. In Java 8, you will often write code which converts a Collection e.g. List or Set to Stream and then applies some logic using functional programming methods like the filter, map, flatMap and then converts the result back to the Collection e.g. List, Set or Map. In this last part, the collect() method of Stream helps. It accepts a Collector to accumulate elements of Stream into specified Collection. The Collector class provides different methods e.g. toList(), toSet(), toMap(), and toConcurrentMap() to collect the result of Stream into List, Set, Map, and ConcurrentMap in Java.

It also provides a special toCollection() method which can be used to collect Stream elements into a specified Collection e.g. ArrayList, Vector, LinkedList or HashSet.

In this article, we'll see a couple of examples of Stream's collector method to collect the result of stream processing into a List, Set, and Map in Java.


1. Stream to List using collect()

You can collect the result of a Stream processing pipeline in a list by using the Collectors.toList() method. Just pass the Collectors.toList() to collect() method as shwon below:

List<String> listOfStringStartsWithJ
 = listOfString
     .stream()
     .filter( s -> s.startsWith("J"))
     .collect(Collectors.toList());


The list returned by the collect method will have all the String which starts with "J" in the same order they appear in the original list because both Stream and List keep elements in order.


1. Stream to Set using toSet()

You can use Collectors.toSet() method along with collect() to accumulate elements of a Stream into a Set. Since Set doesn't provider ordering and doesn't allow duplicate, any duplicate from Stream will be discarded and order of elements will be lost.

Here is an example to convert Stream to Set using collect() and Collectors in Java 8:

Java 8 - Stream.collect() Example


The set of String in this example contains all the String which starts with letter C e.g. C and C++. The order will be lost and any duplicate will be removed.



3. Stream to Map using toMap()

You can create a Map from elements of Stream using collect() and Collectors.toMap() method. Since Map store two objects i.e. key and value and Stream contains just one element, you need to provide the logic to extract key and value object from Stream element.

For example, if you have a Stream of String then you can create a Map where the key is String itself and value is their length, as shown in the following example:

Map<String, Integer> stringToLength 
   = listOfString
        .stream()
        .collect(
            Collectors.toMap(Function.identity(), String::length));

The Function.identity() used here denotes that same object is used as a key. Though you need to be a little bit careful since Map doesn't allow duplicate keys if your Stream contains duplicate elements than this conversion will fail.

In that case, you need to use another overloaded toMap() method also accepts an argument to resolve conflict in case of duplicate keys. Also, toMap() doesn't provide any guarantee on what kind of Map is returned.


3. Stream to Collection using toCollection()

You can also collect or accumulate result of Stream processing into Collection of your choice e.g ArrayList, HashSet, or LinkedList. There is also a toCollection() method in the Collectors class which allows you to convert Stream to any collection. In the following example, we will learn how to collect Stream elements into an ArrayList.

ArrayList<String> stringWithLengthGreaterThanTwo 
  = listOfString
      .stream()
      .filter( s -> s.length() > 2)
      .collect(Collectors.toCollection(ArrayList::new));

Since ArrayList is a list, it provides ordering guarantee, hence all the elements in the ArrayList will be in the same order they appear in original List and Stream. 

If you find Javadoc boring then you can also join Complete Java MasterClass or read Core Java SE 9 for the Impatient (2nd Edition) to learn more about them.

Java 8 - Stream.collect() Example



Java Program to Use Stream.collect() method

Here is our complete Java program to demonstrate the use of collect() method of Stream class to convert Stream into different Collection classes in Java e.g. List, Set, Map, and Collection itself.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Code {

  public static void main(String[] args) {

    List<String> listOfString = Arrays.asList("Java", "C", "C++", "Go",
        "JavaScript", "Python", "Scala");
    System.out.println("input list of String: " + listOfString);

    // Example 1 - converting Stream to List using collect() method
    List<String> listOfStringStartsWithJ
                              = listOfString.stream()
                                            .filter(s -> s.startsWith("J"))
                                            .collect(Collectors.toList());

    System.out.println("list of String starts with letter J: "
        + listOfStringStartsWithJ);

    // Example 2 - converting Stream to Set
    Set<String> setOfStringStartsWithC 
                      = listOfString.stream()
                                    .filter(s -> s.startsWith("C"))
                                    .collect(Collectors.toSet());

    System.out.println("set of String starts with letter C: "
        + setOfStringStartsWithC);

    // Example 3 - converting Stream to Map
    Map<String, Integer> stringToLength 
                          = listOfString.stream()
                                         .collect(Collectors.toMap(Function.identity(),
                                                                    String::length));
    System.out.println("map of string and their length: " + stringToLength);

    // Example - Converting Stream to Collection e.g. ArrayList
    ArrayList<String> stringWithLengthGreaterThanTwo
                        = listOfString.stream()
                                      .filter(s -> s.length() > 2)
                                      .collect(Collectors.toCollection(ArrayList::new));
    System.out.println("collection of String with length greather than 2: "
        + stringWithLengthGreaterThanTwo);

  }
}

Output
input list of String: 
[Java, C, C++, Go, JavaScript, Python, Scala]
list of String starts with letter J: 
[Java, JavaScript]
set of String starts with letter C: 
[C++, C]
map of string and their length: 
{Java=4, C++=3, C=1, Scala=5, JavaScript=10, Go=2, Python=6}
collection of String with length greather than 2: 
[Java, C++, JavaScript, Python, Scala]



That's all about how to use the collect() method of Stream class in Java 8. Along with collect(), you can use Collectors method to convert Stream to List, Set, Map, or any other Collection of your choice. Just explore the Collectors Javadoc to learn more about those methods.

Further Reading
What's New in Java 8
The Ultimate Java 8 Tutorial
Java SE 8 New Features

Related Java 8 Tutorials
If you are interested in learning more about new features of Java 8, here are my earlier articles covering some of the important concepts of Java 8:
  • How to join String in Java 8 (example)
  • How to use filter() method in Java 8 (tutorial)
  • How to use Stream class in Java 8 (tutorial)
  • How to use forEach() method in Java 8 (example)
  • 20 Examples of Date and Time in Java 8 (tutorial)
  • 5 Books to Learn Java 8 from Scratch (books)
  • How to convert List to Map in Java 8 (solution)
  • How to use peek() method in Java 8 (example)

Thanks for reading this article so far. If you like this Java 8 Stream tutorial then please share with your friends and colleagues. I fyou have any questions or feedback then please drop a note.

No comments:

Post a Comment