2016-03-01 2 views
5
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 так, что он имеет записей:Обновление значения в карте на основе другой карты в Java

  • «k1», «знач1»,
  • "k2", "val2",
  • "к3", "val3"

Мое решение:

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

Есть ли лучший способ сделать это?

Edit: Я использую Java 7, но хотелось бы знать, если есть ли лучший способ в Java 8.

+0

Не совсем, нет - хотя похоже, что вы должны делать 'map3.put' вместо' map1.put'? –

+1

это java 8? в этом случае потоки могут вам помочь. – njzk2

+0

Кроме того, вы должны делать 'map2.put' вместо' map1.put' при заполнении 'map2'. – Atri

ответ

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

Любые комментарии для Java 7? –

+0

@dev ツ Честно говоря, кроме случая, о котором я упоминал (карта не имеет соответствующего ключа), на самом деле нет места для улучшения. Все в порядке. – Tunaki

0

в Java 8 вы можете написать:

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

Не самая хорошая вещь, хотя, но все-таки, не мутирует решение.

+0

любой лучший способ в Java7? –

1

Для Java 7 нет ничего более того, что вы можете сделать, вы уже делаете это наилучшим образом.

Я добавляю этот ответ в качестве ссылки, чтобы показать, что для такого случая использование Лямбда-выражений в Java 8 будет даже хуже. Смотрите этот пример:

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».

Смежные вопросы