2016-03-01 22 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"); 

voglio aggiornare i valori di map1 in modo che abbia le voci:Valori aggiornamento nel mappa sulla base di altra mappa in Java

  • "K1", "val1",
  • "k2", "val2",
  • "K3", "val3"

La mia soluzione:

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

C'è un modo migliore per farlo?

Edit: Sto usando Java 7, ma curioso di sapere se esiste un modo migliore in Java 8.

+0

Non proprio, no, anche se sembra che dovresti fare 'map3.put' invece di' map1.put'? –

+1

è questo java 8? in tal caso, i flussi possono aiutarti. – njzk2

+0

Inoltre, si dovrebbe fare 'map2.put' invece di' map1.put' quando si popola 'map2'. – Atri

risposta

3

partire con Java 8, si può solo avere

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

replaceAll(function) sostituirà tutti i valori dalla mappa map1 con il risultato dell'applicazione della funzione specificata. In questo caso, la funzione recupera semplicemente il valore da map2.

Si noti che questa soluzione presenta gli stessi problemi del codice iniziale: se map2 non ha un mapping corrispondente, verrà restituito null. Potresti voler chiamare getOrDefault per avere un valore predefinito in quel caso.

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

Qualche commento per Java 7? –

+0

@dev ツ Onestamente, a parte il caso che ho menzionato (la mappa non ha la chiave corrispondente), non c'è davvero spazio per miglioramenti. Va bene così com'è. – Tunaki

0

in Java 8 è possibile scrivere:

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

Non è la cosa più bella, però, ma ancora una soluzione non-mutanti.

+0

un modo migliore in Java7? –

1

Per Java 7 non c'è nient'altro che puoi fare, lo stai già facendo nel miglior modo possibile.

Aggiungo questa risposta come riferimento per mostrare che, in questo caso, utilizzare Lambda Expressions in Java 8 sarà ancora peggiore. Vedi questo esempio:

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

L'uscita di questo sarà:

Time after for loop 40 
Time after for loop 100 

Il secondo ciclo è variabile, ma sempre più grande rispetto al primo.

io non sono esperto Lambda ma immagino che ci sono più di essere trattati con esso di un semplice "foreach" del primo scenario

esecuzione di questo banco di prova più e più volte si ottiene per lambda quasi sempre il doppio del tempo del primo caso "foreach".