Converting an ArrayList to a HashMap using method references in Java 8 provides a clean and concise way to transform collections with the Stream API. It improves code readability while reducing the need for verbose lambda expressions.
- Uses the Stream API and method references (ClassName::methodName) to convert a list into a HashMap.
- Produces cleaner, more maintainable, and expressive code compared to traditional iteration approaches.
Syntax
Map<KeyType, ValueType> map = list.stream()
.collect(Collectors.toMap(
ClassName::getKey,
ClassName::getValue
));
- ClassName::getKey Method reference used to generate the key for the map.
- ClassName::getValue Method reference used to generate the value for the map.
Using Method Reference
A method reference is a shorthand form of a lambda expression that refers to an existing method. It makes the code more concise and readable when the lambda expression simply invokes an already defined method.
- Method references improve code readability by replacing simple lambda expressions with a compact syntax.
- They can be used with the Stream API to generate keys and values without writing explicit lambda expressions.
Convert an ArrayList to HashMap
To convert an ArrayList into a HashMap, follow these steps:
- Create an ArrayList containing objects.
- Define getter methods for the key and value fields.
- Convert the list into a stream using stream().
- Use Collectors.toMap() with method references.
- Store the result in a HashMap or Map.
import java.io.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
class GFG {
public static void main(String[] args)
{
// creating arraylist to add elements
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Banana");
fruits.add("Guava");
fruits.add("Pineapple");
fruits.add("Apple");
// printing contents of arraylist before conversion
System.out.println("Elements in ArrayList are : "
+ fruits);
// creating new hashmap and using method reference
// with necessary classes for the conversion
HashMap<String, Integer> res = fruits.stream().collect(Collectors.toMap(
Function.identity(), String::length,
(e1, e2) -> e1, HashMap::new));
// printing the elements of the hashmap
System.out.println("Elements in HashMap are : "
+ res);
}
}
Output
Elements in ArrayList are : [Banana, Guava, Pineapple, Apple]
Elements in HashMap are : {Guava=5, Apple=5, Pineapple=9, Banana=6}
Handle Duplicate Keys while Converting
If duplicate keys exist, Collectors.toMap() throws an IllegalStateException unless a merge function is provided.
import java.util.*;
import java.util.stream.Collectors;
class Student {
private int rollNo;
private String name;
public Student(int rollNo, String name) {
this.rollNo = rollNo;
this.name = name;
}
public int getRollNo() {
return rollNo;
}
public String getName() {
return name;
}
}
public class Main {
public static void main(String[] args) {
ArrayList<Student> students = new ArrayList<>();
students.add(new Student(101, "Rahul"));
students.add(new Student(102, "Priya"));
students.add(new Student(101, "Aman"));
Map<Integer, String> studentMap =
students.stream()
.collect(Collectors.toMap(
Student::getRollNo,
Student::getName,
(oldValue, newValue) -> oldValue
));
System.out.println(studentMap);
}
}
Output
{101=Rahul, 102=Priya}
What Happens if Duplicate Keys Are Not Handled?
If duplicate keys are present and no merge function is specified, Java throws an exception.
Exception in thread "main" java.lang.IllegalStateException: Duplicate key 101
Advantages of Using Method References
- Makes code shorter and easier to read.
- Eliminates unnecessary lambda expressions.
- Integrates seamlessly with the Java Stream API.
- Encourages reusable and maintainable code.
Another Approche using a Lambda Expression
A lambda expression is an anonymous function introduced in Java 8 that allows you to write functional code in a concise manner. When converting an ArrayList to a HashMap, lambda expressions can be used to define how the keys and values are generated for each element.
- Lambda expressions provide an inline implementation of functional interfaces, reducing the need for anonymous classes.
- They offer flexibility by allowing custom logic for generating keys and values during the conversion process.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
public class GFG {
public static void main(String[] args) {
// Creating an ArrayList
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Banana");
fruits.add("Guava");
fruits.add("Pineapple");
fruits.add("Apple");
System.out.println("Elements in ArrayList: " + fruits);
// Converting ArrayList to HashMap using Lambda Expression
HashMap<String, Integer> map = fruits.stream()
.collect(Collectors.toMap(
fruit -> fruit, // Key
fruit -> fruit.length(), // Value
(oldValue, newValue) -> oldValue,
HashMap::new));
System.out.println("Elements in HashMap: " + map);
}
}
Output
Elements in ArrayList: [Banana, Guava, Pineapple, Apple]
Elements in HashMap: {Guava=5, Apple=5, Pineapple=9, Banana=6}