Java - Convert List to Map

How to convert List to Map.

Simple way

First, I have an Item class that stores Id and Value like this:

public class Item {
    private int id;
    private String value;
    public Item(int id, String value) {
        this.id = id;
        this.value = value;
    }

    public int getId() {
        return id;
    }

    public String getValue() {
        return value;
    }
}

The code below is an example of converting List to Map using for-loop.

List<Item> list = new ArrayList<>();
list.add(new Item(1, "first"));
list.add(new Item(2, "second"));
list.add(new Item(3, "third"));

Map<Integer, String> map = new HashMap<>();
for (Item item : list) {
    map.put(item.getId(), item.getValue());
}

System.out.println(map);

Output:

{1=first, 2=second, 3=third}

How to use Stream

Using Stream and Collectors.toMap(), you can convert List to Map as follows.

List<Item> list = new ArrayList<>();
list.add(new Item(1, "first"));
list.add(new Item(2, "second"));
list.add(new Item(3, "third"));

Map<Integer, String> map = list.stream().collect(
        Collectors.toMap(Item::getId, Item::getValue));

System.out.println(map);

Output:

{1=first, 2=second, 3=third}

Resolve duplicate issues

The code above has a problem when duplicate data is stored in Map via Stream.

If data with duplicate IDs are input to Map as follows, a runtime error occurs.

List<Item> list = new ArrayList<>();
list.add(new Item(1, "first"));
list.add(new Item(2, "second"));
list.add(new Item(1, "third"));

Map<Integer, String> map = list.stream().collect(
        Collectors.toMap(Item::getId, Item::getValue));

You can solve the problem by passing (oldId, newId) -> oldId as the third argument to (oldId, newId) -> oldId. This code means that when data of the same key is input, the previously saved data of oldId is maintained.

List<Item> list = new ArrayList<>();
list.add(new Item(1, "first"));
list.add(new Item(2, "second"));
list.add(new Item(1, "third"));

Map<Integer, String> map = list.stream().collect(
        Collectors.toMap(Item::getId,
                Item::getValue,
                (oldId, newId) -> oldId
        ));

System.out.println(map);

Output:

{1=first, 2=second}

If you pass an argument to (oldId, newId) -> newId, the old data is deleted and overwritten with the new data.

Map<Integer, String> map = list.stream().collect(
        Collectors.toMap(Item::getId,
                Item::getValue,
                (oldId, newId) -> newId
        ));

Output:

{1=third, 2=second}

Convert to desired Map

Collectors.toMap() creates a HashMap by default. If you want to create a Map with ConcurrentHashMap, pass ConcurrentHashMap::new as an argument as shown below. The method is the same for other Map objects.

Map<Integer, String> map = list.stream().collect(
        Collectors.toMap(Item::getId,
                Item::getValue,
                (oldId, newId) -> oldId,
                ConcurrentHashMap::new
        ));

Sort Map

LinkedHashMap is a Map that guarantees the input order. If you sort Stream data with sorted() and store it in a Map, the sorted order is maintained.

The code below stores data sorted in reverse order of Id in Map.

List<Item> list = new ArrayList<>();
list.add(new Item(1, "first"));
list.add(new Item(2, "second"));
list.add(new Item(3, "third"));

Map<Integer, String> map = list.stream()
        .sorted(Comparator.comparingLong(Item::getId).reversed())
        .collect(Collectors.toMap(Item::getId,
                    Item::getValue,
                    (oldId, newId) -> oldId,
                    LinkedHashMap::new
                ));

System.out.println(map);

Output:

{3=third, 2=second, 1=first}
codechachaCopyright ©2019 codechacha