Got a List object that you'd like to transform into a sorted Map?

Good. Cuz I'll show you how to do it here.

Even better: I'll show you how to do it easily with the assistance of the Java Stream API. Then you can impress your friends and managers.

Let's get started.

The Use Case

The use case here is you've got a List of Employee objects. You want to transform that List into a Map with the employee's last name as the key.

That's normally a bad idea because lots of employees have the same last name. But for the purposes of this simple guide it will work.

However, you also want that Map sorted alphabetically by the employee's last name. 

In other words, sorted alphabetically by key.

A Tree By Any Other Name

Whenever you hear "we need a Map sorted by the key," you should immediately think TreeMap. Because TreeMap sorts the Map automagically based on the natural ordering of the key.

Since the key in this situation is the employee's last name, that's going to work out well because it's usually a great idea to sort people's name alphabetically by last name.

So the finished product here will be a TreeMap object. 

The Model

Here's what the model looks like:

public class Employee {

    private String id;    
    private String lastName;
    private String firstName;

//getters and setters

It's got just three (3) properties: id, lastName, and firstName.

We'll use that class to create some test data as follows:

List<Employee> employees = new ArrayList<>();

Employee employee1 = new Employee();

Employee employee2 = new Employee();

Employee employee3 = new Employee();

That's going to give you a List object of three (3) employees.

Now let me show you how to put that into a sorted Map.

Planting the Seed

You're going to grow that tree by planting the seed with a Stream object. Here's what the code looks like:

TreeMap<String, Employee> sortedMap = employees
                                        .collect(Collectors.toMap(Employee::getLastName, Function.identity(), (o, n) -> n, TreeMap::new));

The Stream object gets instantiated thanks to the stream() method from the employees object.

Then the code invokes the collect() method from the Stream object to perform a reduction. But it needs a Collector object to specify the type and manner of the reduction.

The word "reduction" here, by the way, is just geek-speak for "take many things and turn it into one thing." In this case, it will take all those Employee objects and transform them into a single TreeMap.

The Collector used here is instantiated with the static toMap() method from Collectors.

That toMap() method is overloaded. Here, the code uses the version of the method that includes a supplier. I'll explain that in a moment.

The first parameter in toMap() is the key in the map. In this case, it's the last name retrieved as a function with the method reference notation Employee::getLastName.

The second parameter is the value that gets associated with that key in the map. It's Function.identity() which means "the entire Employee object."

The third parameter is the merge function. It tells the application what to do if it encounters collisions. The lambda expression (o, n) -> n simply means "if there's a collision between an old object (o) and a new object (n), take the new object." 

And that last parameter is the supplier I mentioned eariler. It instantiates TreeMap and populates that object with the results produced by the Collector.

And that's it. If you print out the results of that code above, you'll see the following:

{Cheshire=playground.Employee@1d251891[firstName=Bunny,id=B12,lastName=Cheshire], Kin=playground.Employee@4411d970[firstName=Glenn,id=C11,lastName=Kin], Smith=playground.Employee@6442b0a6[firstName=Frank,id=A17,lastName=Smith]}

Look carefully and you'll see that Map object is sorted alphabetically by last name.

Wrapping It Up

Now you know how to transform a List object into a sorted Map. Feel free to apply what you've learned here to any development work you're handling right now.

Have fun!