Java 8 – Stream collect() method with examples

In this article, we will discuss Stream’s collect() method in details with examples

1. Stream collect() method :

  • This Stream method is a terminal operation which reads given stream and returns a collection like List or Set (or Map)
  • There are 2 variants of collect() method and we are going discuss only one as mentioned below
  • Method signature :- <R, A> R collect(Collector<? super T, A, R> collector)
  • collect() method accepts Collectors which is a final class with various utility methods to perform reduction on the given Stream
  • To be very precise, we are going to discuss only 4 methods namely
    1. Collectors.toList() to convert to List
    2. Collectors.toSet() to convert to Set
    3. Collectors.toCollection() to convert any Collection class like ArrayList/HashSet
    4. Collectors.toMap() to convert to Map



2. Stream collect() method – Collect to List :

  • Collectors.toList() converts the given Stream elements into List which is in ordered fashion

2.1 Collect to List after modification/altering/filtering

  • First list contains integer numbers
  • We are going to double the integer numbers by multiplying by 2 using map() method and store it into new List using collect() method
  • Second list contains String elements
  • We are going to filter elements for String containing letter ‘i‘ using filter() method and store it into new List using collect() method
package net.bench.resources.stream.collect.example;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamCollectToList {

	public static void main(String[] args) {

		// 1. integer numbers
		List<Integer> numbers = Arrays.asList(1,2,3,4,5);
		System.out.println("Original numbers :- " 
				+ numbers);

		// 1.1 collect to new list after doubling
		List<Integer> doubledNumbers = numbers
				.stream()
				.map(num -> num * 2)
				.collect(Collectors.toList());

		// 1.2 print to console
		System.out.println("Doubled numbers  :- " 
				+ doubledNumbers);

		// 2. list of Strings
		List<String> names = Arrays.asList(
				"Viraj",
				"Suresh",
				"Krishnanand",
				"Aditya",
				"Rishi"
				);
		System.out.println("\nOriginal list of names :- "
				+ names);

		// 2.1 collect to new list - names containing 'i'
		List<String> namesContainingI = names
				.stream()
				.filter(name -> name.contains("i"))
				.collect(Collectors.toList());

		// 2.2 print to console
		System.out.println("Names containing 'i'   :- " 
				+ namesContainingI);
	}
}

Output:

Original numbers :- [1, 2, 3, 4, 5]
Doubled numbers  :- [2, 4, 6, 8, 10]

Original list of names :- [Viraj, Suresh, Krishnanand, Aditya, Rishi]
Names containing 'i'   :- [Viraj, Krishnanand, Aditya, Rishi]

2.2 Collect Students to new List based on Age

  • A list contains 5 Students with information like Id, name and age
  • We are going to filter Students on the basis of their age which should be under 19 using filter() method and store it into new List using collect() method

Student.java

package net.bench.resources.stream.collect.example;

public class Student {

	// member variables
	private int rollNumber;
	private String name;
	private int age;

	// constructors
	public Student(int rollId, String name, int age) {
		super();
		this.rollNumber = rollId;
		this.name = name;
		this.age = age;
	}

	// getters & setters
	public int getRollId() {
		return rollNumber;
	}
	public void setRollId(int rollId) {
		this.rollNumber = rollId;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}

	// toString()
	@Override
	public String toString() {
		return "Student [rollNumber=" + rollNumber 
				+ ", name=" + name 
				+ ", age=" + age 
				+ "]";
	}

	// hashCode()
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + rollNumber;
		return result;
	}

	// equals()
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (rollNumber != other.rollNumber)
			return false;
		return true;
	}
}

StreamCollectToListForStudents.java

package net.bench.resources.stream.collect.example;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import net.bench.resources.stream.min.max.example.Student;

public class StreamCollectToListForStudents {

	public static void main(String[] args) {

		// 1. list of students
		List<Student> students = Arrays.asList(
				new Student(1, "Viraj", 17),
				new Student(2, "Krishnanand", 18),
				new Student(3, "Rishi", 16),
				new Student(4, "Suresh", 23),
				new Student(5, "Aditya", 21)
				);

		// 1.1 print all Students to console
		System.out.println("Original list of Students :-\n");
		students.stream().forEach(student -> System.out.println(student));

		// 2. get Students with Age less than 19 into new List
		List<Student> ageLessThan19 = students
				.stream()
				.filter(student -> student.getAge() < 19)
				.collect(Collectors.toList());

		// 2.1 print to console after collecting to new List
		System.out.println("\n\nStudents with Age less than 19 :-\n");
		ageLessThan19.stream().forEach(student -> System.out.println(student));
	}
}

Output:

Original list of Students :-

Student [rollNumber=1, name=Viraj, age=17]
Student [rollNumber=2, name=Krishnanand, age=18]
Student [rollNumber=3, name=Rishi, age=16]
Student [rollNumber=4, name=Suresh, age=23]
Student [rollNumber=5, name=Aditya, age=21]


Students with Age less than 19 :-

Student [rollNumber=1, name=Viraj, age=17]
Student [rollNumber=2, name=Krishnanand, age=18]
Student [rollNumber=3, name=Rishi, age=16]

3. Stream collect() method – Collect to Set:

  • Collectors.toSet() converts the given Stream elements into Set which is in unordered fashion and also removes duplicates, if any

3.1 Collect to Set after filtering/altering/modification

  • First list contains integer numbers with duplicates
  • We are going to filter numbers which is less than or equal to 3 using filter() method and store it into new Set using collect() method
  • Second list contains String elements and few string elements are duplicated
  • We are going to convert String elements into upper case using map() method and store it into new Set using collect() method
  • Note: Collectors.toSet() – removes duplicates while storing into Set
package net.bench.resources.stream.collect.example;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class StreamCollectToSet {

	public static void main(String[] args) {

		// 1. integer numbers
		List<Integer> numbers = Arrays.asList(
				1,2,3,4,5,
				1,2,3,4,5
				);
		System.out.println("Original numbers with duplicates :- " 
				+ numbers);

		// 1.1 collect to Set which ignores duplicates
		Set<Integer> uniqueNumbers = numbers
				.stream()
				.filter(num -> num <= 3)
				.collect(Collectors.toSet()); // removes duplicates

		// 1.2 print to console
		System.out.println("Unique numbers under 3 in Set  :- " 
				+ uniqueNumbers);

		// 2. list of Strings
		List<String> names = Arrays.asList(
				"Viraj",
				"Suresh",
				"Krishnanand",
				"Aditya",
				"Rishi",
				"Viraj",
				"Suresh"
				);
		System.out.println("\n\nOriginal list of names with duplicates :- \n"
				+ names);

		// 2.1 collect to new Set ignoring duplicates names
		Set<String> uniqueNames = names
				.stream()
				.map(name -> name.toUpperCase())
				.collect(Collectors.toSet()); // removes duplicates

		// 2.2 print to console
		System.out.println("\nUpper case unique names in Set :- \n"
				+ uniqueNames);
	}
}

Output:

Original numbers with duplicates :- [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
Unique numbers under 3 in Set  :- [1, 2, 3]


Original list of names with duplicates :- 
[Viraj, Suresh, Krishnanand, Aditya, Rishi, Viraj, Suresh]

Upper case unique names in Set :- 
[VIRAJ, RISHI, SURESH, KRISHNANAND, ADITYA]

3.2 Collect Students to new Set based on Age

  • A list contains 6 Students with information like Id, name and age
  • Student with Id 5 whose age is 19 which is under 20 is duplicated twice in the original List
  • We are going to filter Students on the basis of their age which should be under 20 using filter() method and store it into new Set using collect() method
  • For Student with Id 5, only one time information will be stored into Set, as Set doesn’t allow duplicates. For this we have to override hashCode() and equals() methods in Student class
  • Note: we are using the same Student class mentioned in the Collectors.toList() method example
package net.bench.resources.stream.collect.example;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import net.bench.resources.stream.min.max.example.Student;

public class StreamCollectToSetForStudents {

	public static void main(String[] args) {

		// 1. list of students
		List<Student> students = Arrays.asList(
				new Student(1, "Viraj", 17),
				new Student(2, "Krishnanand", 21),
				new Student(3, "Rishi", 16),
				new Student(4, "Suresh", 23),
				new Student(5, "Aditya", 19),
				new Student(5, "Aditya", 19) // duplicate
				);

		// 1.1 print all Students to console
		System.out.println("Original list of Students :-\n");
		students.stream().forEach(student -> System.out.println(student));

		// 2. get Students with Age less than 19 into new List
		Set<Student> ageLessThan19 = students
				.stream()
				.filter(student -> student.getAge() < 20)
				.collect(Collectors.toSet());

		// 2.1 print to console after collecting to new List
		System.out.println("\n\nStudents with Age less than 20 :-\n");
		ageLessThan19.stream().forEach(student -> System.out.println(student));
	}
}

Output:

Original list of Students :-

Student [rollNumber=1, name=Viraj, age=17]
Student [rollNumber=2, name=Krishnanand, age=21]
Student [rollNumber=3, name=Rishi, age=16]
Student [rollNumber=4, name=Suresh, age=23]
Student [rollNumber=5, name=Aditya, age=19]
Student [rollNumber=5, name=Aditya, age=19]


Students with Age less than 20 :-

Student [rollNumber=1, name=Viraj, age=17]
Student [rollNumber=5, name=Aditya, age=19]
Student [rollNumber=3, name=Rishi, age=16]

4. Stream collect() method – Collect to any Collection:

  • In earlier examples, Collectors.toList() and Collectors.toSet() methods are used to convert a Stream to directly List and Set respectively
  • But Collectors.toCollection() method allows us to choose the Collection class representation we want to convert a Stream to like ArrayList, LinkedList, HashSet, etc.

4.1 Collect to ArrayList and HashSet after filtering

  • A list contains String elements
  • First, we are going to filter elements for String containing letter ‘i‘ using filter() method and store it into ArrayList using collect() method (constructor reference approach) which is in ordered fashion
  • Second, we are going to filter elements for String containing letter ‘i‘ using filter() method and store it into HashSet using collect() method (constructor reference approach) which is in unordered fashion
package net.bench.resources.stream.collect.example;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

public class StreamCollectToCollection {

	public static void main(String[] args) {

		// 1. list of Strings
		List<String> names = Arrays.asList(
				"Viraj",
				"Suresh",
				"Krishnanand",
				"Aditya",
				"Rishi"
				);
		System.out.println("Original list of names :- "
				+ names);

		// 1.1 collect to Ordered ArrayList with names containing 'i'
		ArrayList<String> orderedNamesContainingI = names
				.stream()
				.filter(name -> name.contains("i"))
				.collect(Collectors.toCollection(ArrayList::new));

		// 1.2 print to console
		System.out.println("\nOrdered names containing"
				+ " 'i' in ArrayList :- " + orderedNamesContainingI);

		// 2.1 collect to Unordered HashSet with names containing 'i'
		HashSet<String> unOrderedNamesContainingI = names
				.stream()
				.filter(name -> name.contains("i"))
				.collect(Collectors.toCollection(HashSet::new));

		// 2.2 print to console
		System.out.println("\nUnordered names containing"
				+ " 'i' in HashSet :- " + unOrderedNamesContainingI);
	}
}

Output:

Original list of names :- [Viraj, Suresh, Krishnanand, Aditya, Rishi]

Ordered names containing 'i' in ArrayList :- [Viraj, Krishnanand, Aditya, Rishi]

Unordered names containing 'i' in HashSet :- [Viraj, Krishnanand, Rishi, Aditya]

5. Stream collect() method – Collect to Map:

  • Collectors.toMap() is used to convert the given Stream into Map with Key-Value pair as entries

5.1 Collect to Map

  • A list contains String elements
  • We are going to store String elements as Key and its length as Value
  • Collectors.toMap() accepts 2 arguments, 1st it take Function.identity() as Key and 2nd String::length for String length calculation as Value
package net.bench.resources.stream.collect.example;

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

public class StreamCollectToMap {

	public static void main(String[] args) {

		// 1. list of Strings
		List<String> names = Arrays.asList(
				"Viraj",
				"Suresh",
				"Krishnanand",
				"Aditya",
				"Rishi"
				);
		System.out.println("Original list of names :- "
				+ names);

		// 1.1 collect to map along with length
		Map<String, Integer> mapStringLenth = names
				.stream()
				.collect(Collectors
						.toMap(Function.identity(), String::length));

		// 1.2 print to console
		System.out.println("\nMap :- " + mapStringLenth);
	}
}

Output:

Original list of names :- [Viraj, Suresh, Krishnanand, Aditya, Rishi]

Map :- {Suresh=6, Viraj=5, Krishnanand=11, Rishi=5, Aditya=6}

References:

Happy Coding !!
Happy Learning !!

Java 8 - Stream concat() method for merging elements
Java 8 - Filter a Map by its Key and Value