Java Stream APIs Tutorial: How To Use .collect and .sorted With Example

Jingnu An
3 min readAug 7, 2023

Stream operations enable Java developers to perform tasks with ease and elegance. In this article, I use two examples to introduce two Stream APIs, .collect() and .sorted() .

Turn A List Into A Map Using .collect

We have a list of Customer, and each Customer has a field named customerId. The goal is to create a map that uses the customerId as key, and the Customer object reference as value.

class Customer {
private String customerId;
public Customer(String id){ this.customerId = id; }
public String getCustomerId(){ return this.customerId; }
}

class Example {
public static void main(String[] args){
List<Customer> customers = new ArrayList<>();
customers.add(new Customer("001"))
customers.add(new Customer("002"));

/*
create a map that uses the customerId as key,
and the Customer object reference as value. Insert your code below:
*/

}
}

I used to write:

Map<String, Customer> map = new HashMap<>();
for(Customer c : customers){
map.putIfAbsent(c.getCustomerId(), c);
}

But since I learned how to use stream, I can also write:

Map<String, Customer> map = customers.stream().collect(Collectors.toMap(Customer::getCustomerId, customer -> customer));

Let’s break down the above one-liner step by step:

  • customers.stream(): The stream() method is called on the customers list, which converts it into a stream. A stream is a sequence of elements that can be processed sequentially or in parallel using stream operations.
  • .collect(Collectors.toMap(Customer::getCustomerId, customer -> customer)): .collect is a terminal operation in the Java 8 Stream API. In this example, the stream elements are collected into a map using the toMap collector.
  • Customer::getCustomerId: This is a method reference that refers to the getCustomerId() method of the Customer class. It is used as the key mapper for the toMap collector, meaning it extracts the customerId from each Customer object to use as the key in the resulting map.
  • customer -> customer: This lambda expression represents the value mapper for the toMap collector. It specifies that the original Customer object should be used as the value in the resulting map.

🤔 This is a good point to stop and ponder. Can you answer the following two questions?

1. Can you write out all entries in the map from the above code example?

2. You have a list of Recipe and each Recipe has a field recipeName, can you use .collect to create a map with recipeName as the key and the Recipe object reference as its value?

Sort A List of Object Using .sorted

There is a list of Players and each Player has a field named score. The field score is a double. The goal is to sort the list based on each Player’s score in ascending order.

class Player {
private String id;
private double score;
public Player(String id, double score){ ... }
public double getScore(){return this.score; }
}

class Example2 {
public static void main(String[] args){
List<Player> players = new ArrayList<>();
players.add(new Player("001", 89.3));
players.add(new Player("002", 79.8));

/*
sort the player list based on each Player's score in ascending order.
Insert your code below:
*/
}
}

I used to use List.sort like below:

players.sort(Comparator.comparingDouble(Player::getScore));

but since I learned how to use stream, I can also write:

players.stream()
.sorted(Comparator.comparingDouble(Player::getScore))
.toList();

Let’s break it down step by step:

  • .stream(): The stream() method is called on the players collection, which converts it into a stream. A stream is a sequence of elements that can be processed sequentially or in parallel using stream operations.
  • .sorted(Comparator.comparingDouble(Player::getScore)): The sorted method is called on the stream to sort the elements based on the Player object's score field. This method requires a Comparator to define the sorting order.
  • Comparator.comparingDouble(Player::getScore): This creates a comparator using the comparingDouble method of the Comparator class. The comparingDouble method takes a function as an argument, and in this case, we use a method reference Player::getScore. It means we're comparing the Player objects based on their score field, which should be of type double.
  • .toList(): This terminal operation collects the elements of the sorted stream into a list.

After performing all the stream operations, the final result is a new list containing the elements of the players collection, sorted in ascending order based on the score field of each Player object.

Thank you for reading! If you enjoyed reading this tutorial please consider share it or give it a 👏 clap (or long press for up to 50 claps! A cool hidden trick in my opinion 😁).

--

--