基于Java中的其他映射更新Map中的值

时间:2016-03-01 16:15:35

标签: java dictionary

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");

我想更新 map1 的值,以便它有条目:

  • &#34; K1&#34; ,&#34; val1&#34;,
  • &#34; K2&#34; ,&#34; val2&#34;,
  • &#34; K3&#34; ,&#34; val3&#34;

我的解决方案:

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

有没有更好的方法呢?

  

编辑:我正在使用Java 7,但很想知道Java 8中是否有更好的方法。

3 个答案:

答案 0 :(得分:3)

从Java 8开始,你可以拥有

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

replaceAll(function)会将地图map1中的所有值替换为应用给定函数的结果。在这种情况下,该函数只是从map2

中检索值

请注意,此解决方案与初始代码存在相同的问题:如果map2没有相应的映射,则会返回null。在这种情况下,您可能希望将getOrDefault调用为默认值。

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}"
}

答案 1 :(得分:1)

对于Java 7,您无法做更多的事情,您已经以最佳方式完成了这项工作。

我正在添加这个答案作为参考,以表明对于这种情况,使用Java 8中的Lambda表达式将是最糟糕的。见这个例子:

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);
}

此输出将为:

Time after for loop 40
Time after for loop 100

第二个循环是可变的,但总是比第一个循环大。

我不是Lambda专家,但我想还有更多要处理它而不是第一个场景的简单“foreach”

一遍又一遍地运行这个测试用例,lambda几乎总是两倍于第一个“foreach”案例的时间。

答案 2 :(得分:0)

在Java 8中你可以写:

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

虽然不是最好的东西,但仍然是一个非变异的解决方案。