This example will show how to convert a list to a map using java, java 8 and guava. For the snippets below, we have created a Movie object. Typically when this this action occurs, the keys of the map are produced based on a specified object method and the values are the elements itself. In a related example we demonstrate how to transform a list to a map in groovy.
Setup
class Movie {
private Integer rank;
private String description;
public Movie(Integer rank, String description) {
super();
this.rank = rank;
this.description = description;
}
public Integer getRank() {
return rank;
}
public String getDescription() {
return description;
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("rank", rank)
.add("description", description)
.toString();
}
}
Straight up Java
When converting a list to a map using the core jdk, a traditional approach can be taken iterating over each element using a for each loop and calling the Map.put with a specified key and value.
@Test
public void convert_list_to_map_with_java () {
List<Movie> movies = new ArrayList<Movie>();
movies.add(new Movie(1, "The Shawshank Redemption"));
movies.add(new Movie(2, "The Godfather"));
Map<Integer, Movie> mappedMovies = new HashMap<Integer, Movie>();
for (Movie movie : movies) {
mappedMovies.put(movie.getRank(), movie);
}
logger.info(mappedMovies);
assertTrue(mappedMovies.size() == 2);
assertEquals("The Shawshank Redemption", mappedMovies.get(1).getDescription());
}
Output
mappedMovies = {
1=Movie{rank=1, description=The Shawshank Redemption},
2=Movie{rank=2, description=The Godfather}
}
Java 8
Converting a list to a map in Java 8 can be performed by first converting the list to a stream and calling the collect terminal operation. In this instance, we will call Collectors.toMap which will return a collector that accumulates elements into a map. The keys are the generated from the Movie::getRank and the values are the Movie object.
@Test
public void convert_list_to_map_with_java8_lambda () {
List<Movie> movies = new ArrayList<Movie>();
movies.add(new Movie(1, "The Shawshank Redemption"));
movies.add(new Movie(2, "The Godfather"));
Map<Integer, Movie> mappedMovies = movies.stream().collect(
Collectors.toMap(Movie::getRank, (p) -> p));
logger.info(mappedMovies);
assertTrue(mappedMovies.size() == 2);
assertEquals("The Shawshank Redemption", mappedMovies.get(1).getDescription());
}
Output
mappedMovies = {
1=Movie{rank=1, description=The Shawshank Redemption},
2=Movie{rank=2, description=The Godfather}
}
Google Guava
Guava Maps utility class contains Maps.uniqueIndex will create a map from a list of values. Each key is produced by calling a supplied function and the value is the value itself. Below, the function will pass in an object Movie and return an Integer by calling the Movie.getRank to create the Map.key.
@Test
public void convert_list_to_map_with_guava () {
// create a list
List<Movie> movies = Lists.newArrayList();
movies.add(new Movie(1, "The Shawshank Redemption"));
movies.add(new Movie(2, "The Godfather"));
// convert list to map
Map<Integer,Movie> mappedMovies = Maps.uniqueIndex(movies, new Function <Movie,Integer> () {
public Integer apply(Movie from) {
return from.getRank(); // or something else
}});
logger.info(mappedMovies);
assertTrue(mappedMovies.size() == 2);
assertEquals("The Shawshank Redemption", mappedMovies.get(1).getDescription());
}
Output
mappedMovies = {
1=Movie{rank=1, description=The Shawshank Redemption},
2=Movie{rank=2, description=The Godfather}
}