0

I have two HashMap in Java.

First one contains a key and its value. Where second contains an evaluation index (order) of that keys. I want to sort the first map by referring to the second map.

First HashMap <key, value>

<"C","ccc">
<"D","ddd">
<"A","aaa">
<"B","bbb">

Second HashMap <key, value>

<"0","A">
<"1","B">
<"2","C">
<"3","D">

Result should be

<"A","aaa">
<"B","bbb">
<"C","ccc">
<"D","ddd">

Looping this two map and checking comparing keys is simple but not efficient. Any efficient idea?

kandarp
  • 991
  • 1
  • 14
  • 35

3 Answers3

7

You can use Java Stream API. First, sort the second map entrySet by key then map second map's value as key and get first map's value by value of the second map and then collect as LinkedHashMap using Collectors.toMap

secondMap.entrySet().stream()
         .sorted(Comparator.comparing(Map.Entry::getKey))
         .collect(Collectors.toMap(Map.Entry::getValue, k -> firstMap.get(k.getValue()),
                                                          (x, y) -> y, LinkedHashMap::new));

If you use LinkedHashMap/TreeMap ordered by key for the second map then you don't need to sort the keys. See demo here

Eklavya
  • 17,618
  • 4
  • 28
  • 57
  • What if the first map is Map. Your code doesn't work – kandarp Aug 12 '20 at 06:03
  • @kandarp It's working see here [demo](https://onlinegdb.com/rJzlwWbMP) – Eklavya Aug 12 '20 at 06:07
  • 1
    `new AbstractMap.SimpleEntry<>` can be `Map.entry`. –  Aug 12 '20 at 06:30
  • @kandarp If the second HashMap is `{"0000000"="A", "1111111"="B", "2222222"="C", "3333333"="D"}`, the result is `{"C"="ccc", "D"="ddd", "B"="bbb", "A"="aaa"}`. Is that all right? –  Aug 12 '20 at 06:56
  • @saka1029 Are you trying to say this case ? https://onlinegdb.com/S1tb4zbGw It's working for me. – Eklavya Aug 12 '20 at 07:03
  • @User-Upvotedon'tsayThanks Since OP says `Second HashMap`, `res1` is meaningless. `res2` uses a different code than your answer. –  Aug 12 '20 at 07:10
  • I think `map` step is not needed at all. The same transformation can be done inside `toMap` – Vladislav Varslavans Aug 12 '20 at 07:28
1

First of all HashMap is not ordered collections. The key-value pairs in HashMap are ordered based on the value of hashCode() result of keys. So I would say you can't keep sorted values in HashMap.

Instead, you can use LinkedHashMap - it will be ordered with order of insertion.

And for your solution, i would do:

HashMap<String, String> firstMap = ...
HashMap<String, String> secondMap = ...
LinkedHashMap<String, String> orderedMap = new LinkedHashMap<>();
for (int i = 0; i < secondMap.size(); ++i) {
   String key = secondMap.get(String.valueOf(i));
   orderedMap.put(key, firstMap.get(key));
}

Did not run this code, but it should work.

Alternatively, you can use TreeMap that is ordered based on Comparable interface of the keys.

And to answer what is better to use - TreeMap or LinkedHashMap - depends on how actually you are using this map later. In most cases LinkedHashMap is enough, although if you need to, for example, get the closest greater element to some key, then TreeMap is a choice.

There are some comparison between HashMap and TreeMap What is the difference between a HashMap and a TreeMap?

Vladislav Varslavans
  • 2,775
  • 4
  • 18
  • 33
0

Traverse the values of secondMap and collect the related key, value set in the map:

Map<String, String> result = secondMap.values().stream()
        .collect(Collectors.toMap(Function.identity(), firstMap::get, (x,y)-> x, LinkedHashMap::new));

Try this:

Map<String, String> firstMap = new HashMap<>();
firstMap.put("C", "ccc");
firstMap.put("D", "ddd");
firstMap.put("A", "aaa");
firstMap.put("B", "bbb");

Map<String, String> secondMap = new HashMap<>();
secondMap.put("0", "A");
secondMap.put("1", "B");
secondMap.put("2", "C");
secondMap.put("3", "D");

Map<String, String> result = secondMap.values().stream()
        .collect(Collectors.toMap(Function.identity(), firstMap::get, (x,y)-> x, LinkedHashMap::new));
System.out.println(result);
Hülya
  • 3,353
  • 2
  • 12
  • 19