5

I am working on sorting a map by values code using java 8.

I have done most of the thing but I am not getting how to convert the list to map using java 8 features

public class SortMapByValue {
public static void main(String[] args) {
    HashMap<String, Integer> map = new HashMap<>();
    map.put("A", 3);
    map.put("V", 1);
    map.put("Anss", 9);
    map.put("D", 5);
    map.put("E", 2);
    map.put("F", 10);

    HashMap<String, Integer> newMap = new LinkedHashMap<>();

    List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());


    Collections.sort(list, (o1, o2) -> o1.getValue() - o2.getValue());

    // Need to this using Java 8 -- start

    for (Entry<String, Integer> entry : list) {
        newMap.put(entry.getKey(), entry.getValue());
    } 

    // Need to this using Java 8 -- end

    newMap.forEach((k, v) -> System.out.println("Key : " + k + " Value : " + v));

    }
}
1
  • 1
    I am working on sorting a map by values => Entry::comparingByValue
    – Eugene
    Commented May 25, 2019 at 18:51

2 Answers 2

5

If you want to sort Map based on values use Entry.comparingByValue() and then collect them to LinkedHashMap :

Map<String,Integer> result =   map.entrySet()
       .stream()
       .sorted(Entry.comparingByValue())
       .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a,b) -> b, LinkedHashMap::new));

In Java-8 there are three overloaded toMap method, the above one is with 4 Parameters which is

public static <T,K,U,M extends Map<K,U>> Collector<T,?,M> toMap(Function<? super T,? extends K> keyMapper,
                                                            Function<? super T,? extends U> valueMapper,
                                                            BinaryOperator<U> mergeFunction,
                                                            Supplier<M> mapSupplier)

Parameters:

keyMapper - a mapping function to produce keys

valueMapper - a mapping function to produce values

mergeFunction - a merge function, used to resolve collisions between values associated with the same key, as supplied to Map.merge(Object, Object, BiFunction)

mapSupplier - a function which returns a new, empty Map into which the results will be inserted

7
  • I understood everything except (a,b)->a, LinkedHashMap::new). what is happening here ? I mean I can see you creating a new instance if LinkedHashMap but what is (a,b) -> a doing ? Commented May 25, 2019 at 20:12
  • The third argument is the merge function. It takes two maps and merges them into one map. I think in this example it is assumed that there will be no duplicate keys and so no two maps actually have to be merged, therefore the merge function can simply return the first map since it will never actually be called. You could presumably put a null there but I haven't tested it. toMap
    – K.Nicholas
    Commented May 25, 2019 at 20:24
  • Third function is uniqueKeyMapper. if there are duplicate keys in your list, then you choose which one to proceed with
    – Rahul B
    Commented May 25, 2019 at 21:24
  • 1
    updated and i agree but since we are processing the Map data i don't think there is any use of merge function @YassinHajaj
    – Ryuzaki L
    Commented May 26, 2019 at 2:24
  • 1
    @Deadpool Indeed in the example we only have unique keys, but following the algorithm 100% is cleaner I think. Nice answer btw Commented May 26, 2019 at 2:27
1
Map map = list.stream().collect(
    Collectors.toMap(
        entry -> entry.getKey(), // keyMapper
        entry -> entry.getValue(), // valueMapper
        (first, second) -> first,  // mergeFunction
        () -> new LinkedHashMap<>() // mapFactory
    )
);

See Stream and Collectors

you can even do that:

public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("A", 3);
        map.put("V", 1);
        map.put("Anss", 9);
        map.put("D", 5);
        map.put("E", 2);
        map.put("F", 10);

        Map newMap = map.entrySet().stream()
            .sorted(Map.Entry.comparingByValue())
            .collect(
                Collectors.toMap(
                    entry -> entry.getKey(), // keyMapper
                    entry -> entry.getValue(), // valueMapper
                    (first, second) -> first,  // mergeFunction
                    () -> new LinkedHashMap<>() // mapFactory
                )
            );

        newMap.forEach((k, v) -> System.out.println("Key : " + k + " Value : " + v));

    }

Not the answer you're looking for? Browse other questions tagged or ask your own question.