Updating values ​​in a Map based on another 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 map1 values ​​to have entries:

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

My decision:

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

Is there a better way to do this?

Edit: I am using Java 7, but I am interested to know if there is a better way in Java 8.

+5
source share
3 answers

Starting with Java 8, you can simply

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

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

Note that this solution has the same problems as your source code: if map2 does not have a matching mapping, null returned. In this case, you can call getOrDefault to have a default value.

 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}" } 
+3
source

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

I am adding this answer as a reference to show that for such a case, using Lambda Expressions in Java 8 would be even worse. 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 would be:

 Time after for loop 40 Time after for loop 100 

The second cycle is variable, but always larger than the first.

I am not a Lambda specialist, but I think that it needs more processing with it than a simple "foreach" of the first script

Running this test again and again you get for lambda almost always twice as much time for the first case of "foreach".

+1
source

in Java 8 you can write:

 map1.entrySet() .stream() .map(entry -> new SimpleEntry(entry.getKey(), map2.get(entry.getValue()))) .collect(Collectors.toMap(entry -> entry.getKey(), entry.getValue())); 

Not the nicest thing, however, but still not a mutating solution.

0
source

Source: https://habr.com/ru/post/1244234/


All Articles