Introduction
In Java 8, the Stream API allows you to process data in a functional and efficient way. You can easily convert a Stream
of elements into a Map
using the Collectors.toMap()
method. This is useful when you need to transform data from a list, set, or other collections into key-value pairs.
In this guide, we will learn how to convert a Stream
to a Map
using Java 8's Collectors.toMap()
method, including handling duplicate keys and specifying custom merging strategies.
Solution Steps
- Create or Obtain a Stream: Generate or obtain a stream from a collection or other data source.
- Use
Collectors.toMap()
: Apply thetoMap()
method to define how to extract the key-value pairs from the stream elements. - Handle Duplicate Keys: Optionally handle cases where duplicate keys exist by providing a merge function.
- Display or Use the Resulting Map: Use or print the resulting map.
Java Program
Example 1: Convert Stream of Strings to a Map
In this example, we convert a stream of strings to a map where the string is the key and its length is the value.
import java.util.stream.Stream;
import java.util.Map;
import java.util.stream.Collectors;
public class StreamToMapExample {
public static void main(String[] args) {
// Step 1: Create a stream of strings
Stream<String> fruitStream = Stream.of("Apple", "Banana", "Orange", "Mango");
// Step 2: Convert the Stream to a Map (key: string, value: length of string)
Map<String, Integer> fruitMap = fruitStream.collect(Collectors.toMap(
fruit -> fruit, // Key: the string itself
fruit -> fruit.length() // Value: the length of the string
));
// Step 3: Display the Map
System.out.println(fruitMap); // Output: {Apple=5, Banana=6, Orange=6, Mango=5}
}
}
Output
{Apple=5, Banana=6, Orange=6, Mango=5}
Explanation
Step 1: Create a Stream of Strings
We create a stream of strings using Stream.of()
:
Stream<String> fruitStream = Stream.of("Apple", "Banana", "Orange", "Mango");
Step 2: Convert the Stream to a Map
We use Collectors.toMap()
to convert the stream into a map where the key is the string itself, and the value is the length of the string:
Map<String, Integer> fruitMap = fruitStream.collect(Collectors.toMap(
fruit -> fruit, // Key: the string itself
fruit -> fruit.length() // Value: the length of the string
));
Step 3: Display the Map
We print the resulting map:
System.out.println(fruitMap);
Example 2: Convert Stream of Custom Objects to a Map
In this example, we convert a stream of Employee
objects to a map where the key is the employee's name, and the value is the employee's age.
import java.util.stream.Stream;
import java.util.Map;
import java.util.stream.Collectors;
public class StreamToMapCustomObjects {
public static void main(String[] args) {
// Step 1: Create a stream of Employee objects
Stream<Employee> employeeStream = Stream.of(
new Employee("Ravi", 30),
new Employee("Amit", 25),
new Employee("Pooja", 35)
);
// Step 2: Convert the Stream to a Map (key: employee name, value: employee age)
Map<String, Integer> employeeMap = employeeStream.collect(Collectors.toMap(
Employee::getName, // Key: employee name
Employee::getAge // Value: employee age
));
// Step 3: Display the Map
employeeMap.forEach((name, age) ->
System.out.println("Name: " + name + ", Age: " + age));
}
}
class Employee {
private String name;
private int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
Output
Name: Ravi, Age: 30
Name: Amit, Age: 25
Name: Pooja, Age: 35
Explanation
Step 1: Create a Stream of Custom Objects
We create a stream of Employee
objects using Stream.of()
:
Stream<Employee> employeeStream = Stream.of(
new Employee("Ravi", 30),
new Employee("Amit", 25),
new Employee("Pooja", 35)
);
Step 2: Convert the Stream to a Map
We use Collectors.toMap()
to convert the stream into a map where the key is the employee's name and the value is the employee's age:
Map<String, Integer> employeeMap = employeeStream.collect(Collectors.toMap(
Employee::getName, // Key: employee name
Employee::getAge // Value: employee age
));
Step 3: Display the Map
We print the resulting map:
employeeMap.forEach((name, age) ->
System.out.println("Name: " + name + ", Age: " + age));
Example 3: Handling Duplicate Keys in toMap()
If the stream contains elements that could generate duplicate keys, you need to provide a merge function to handle the key collisions. In this example, we merge employees with the same name by keeping the employee with the higher age.
import java.util.stream.Stream;
import java.util.Map;
import java.util.stream.Collectors;
public class StreamToMapWithDuplicates {
public static void main(String[] args) {
// Step 1: Create a stream of Employee objects with duplicate names
Stream<Employee> employeeStream = Stream.of(
new Employee("Ravi", 30),
new Employee("Ravi", 35), // Duplicate name with higher age
new Employee("Amit", 25)
);
// Step 2: Convert the Stream to a Map, resolving duplicate keys by keeping the older employee
Map<String, Integer> employeeMap = employeeStream.collect(Collectors.toMap(
Employee::getName, // Key: employee name
Employee::getAge, // Value: employee age
(age1, age2) -> age1 > age2 ? age1 : age2 // Merge function
));
// Step 3: Display the Map
employeeMap.forEach((name, age) ->
System.out.println("Name: " + name + ", Age: " + age));
}
}
class Employee {
private String name;
private int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
Output
Name: Ravi, Age: 35
Name: Amit, Age: 25
Explanation
Step 1: Create a Stream with Duplicate Keys
We create a stream of Employee
objects where two employees have the same name, but different ages:
Stream<Employee> employeeStream = Stream.of(
new Employee("Ravi", 30),
new Employee("Ravi", 35), // Duplicate name
new Employee("Amit", 25)
);
Step 2: Provide a Merge Function for Duplicate Keys
We use Collectors.toMap()
and provide a merge function to resolve duplicate keys by keeping the employee with the higher age:
(employee1, employee2) -> employee1.getAge() > employee2.getAge() ? employee1 : employee2;
Step 3: Display the Map
We print the resulting map:
employeeMap.forEach((name, age) ->
System.out.println("Name: " + name + ", Age: " + age));
Conclusion
In Java 8, converting a stream to a map is easy and flexible using the Collectors.toMap()
method. You can define how keys and values are derived from the stream elements and handle duplicate keys with a custom merge function if necessary. This method is powerful and helps transform streams into key-value mappings in a concise and readable way.
Comments
Post a Comment
Leave Comment