Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating Values in Map on the basis of other map in Java

Map<String, String> map1 = new HashMap<>();
map1.put("k1", "v1");
map1.put("k2", "v2");
map1.put("k3", "v3");

Map<String, String> map2 = new HashMap<>();
map2.put("v1", "val1");
map2.put("v2", "val2");
map2.put("v3", "vav3");

I want to update values of map1 so that it has entries:

  • "k1" , "val1",
  • "k2" , "val2",
  • "k3" , "val3"

My solution:

for (Map.Entry<String, String> entry : map1.entrySet()) {
   map1.put(entry.getKey(), map2.get(entry.getValue()));
}

Is there any better way to do this?

Edit: I am using Java 7 but curious to know if there any better way in Java 8.

like image 483
Dev Avatar asked Sep 25 '22 05:09

Dev


2 Answers

Starting with Java 8, you can just have

map1.replaceAll((k, v) -> map2.get(v));

replaceAll(function) will replace all values from the map map1 with the result of applying the given function. In this case, the function simply retrieves the value from map2.

Note that this solution has the same issues that your initial code: if map2 doesn't have a corresponding mapping, null will be returned. You may want to call getOrDefault to have a default value in that case.

public static void main(String[] args) {
    Map<String, String> map1 = new HashMap<>();
    map1.put("k1", "v1");
    map1.put("k2", "v2");
    map1.put("k3", "v3");

    Map<String, String> map2 = new HashMap<>();
    map2.put("v1", "val1");
    map2.put("v2", "val2");
    map2.put("v3", "val3");

    map1.replaceAll((k, v) -> map2.get(v));

    System.out.println(map1); // prints "{k1=val1, k2=val2, k3=val3}"
}
like image 109
Tunaki Avatar answered Sep 28 '22 03:09

Tunaki


For Java 7 there is nothing more that you can do, you are already doing it in the best way possible.

I'm adding this answer as a reference to show that for such case using Lambda Expressions in Java 8 will be even worst. See this example:

public static void main(String[] args) {
    Map<String, String> map1 = new HashMap<>();
    final Map<String, String> map2 = new HashMap<>();

    for ( int i=0; i<100000; i++ ){
        map1.put("k"+i, "v"+i);
        map2.put("v"+i, "val"+i);
    }

    long time;
    long prev_time = System.currentTimeMillis();
    for (Map.Entry<String, String> entry : map1.entrySet()) {
       map1.put(entry.getKey(), map2.get(entry.getValue()));
    }
    time = System.currentTimeMillis() - prev_time;
    System.out.println("Time after for loop " + time);


    map1 = new HashMap<>();
    for ( int i=0; i<100000; i++ ){
        map1.put("k"+i, "v"+i);
    }

    prev_time = System.currentTimeMillis();
    map1.replaceAll((k, v) -> map2.get(v));
    time = System.currentTimeMillis() - prev_time;
    System.out.println("Time after for loop " + time);
}

The output for this will be:

Time after for loop 40
Time after for loop 100

The second loop is variable but always bigger than the first one.

I'm not Lambda specialist but I guess that there are more to be processed with it than a plain "foreach" of the first scenario

Running this test case over and over you will get for lambda almost always twice the time of the first "foreach" case.

like image 38
Jorge Campos Avatar answered Sep 28 '22 05:09

Jorge Campos