2016-05-30 6 views
0

Ich habe zwei Karten:Java HashMaps mit Key von einem als Wert anderen

map1 = <K , V> 
map2 = <V, someObject> 

Gibt es einen „anmutigen“ Weg, ein Ergebnis der Ausgabe als:

map3 = <K, someObject> 

Eine offensichtliche Möglichkeit wäre, um über map1 zu iterieren und zu tun:

for each entry in map1 { 
    map3.put(entry.getKey(), map2.get(entry.getValue())) 
} 

Idealerweise würde ich Lösungen schätzen, die mit Java 7 kompatibel sind; aber ein kluger ein mit Java 8 wäre für Bildungszwecke gut

Dank

+1

Bitte lesen Sie das Stream-Tutorial https://docs.oracle.com/javase/tutorial/collections/streams/, es wird Ihnen beibringen, wie Sie diese grundlegenden Operationen mit der Stream API durchführen. – Tunaki

Antwort

3

Hier ist ein Java 8 Verfahren, das dies tut:

public static <K1, K2, V> Map<K1, V> java8Version(Map<K1, K2> first, Map<K2, V> second) { 
    return first.entrySet() 
    .stream() 
    .filter(e -> second.containsKey(e.getValue())) 
    .collect(Collectors.toMap(Map.Entry::getKey, e -> second.get(e.getValue()))); 
} 

hinzufügen Optimierungen und null Kontrollen nach Wunsch.

Und hier ist die Java 7 Version:

public static <K1, K2, V> Map<K1, V> java7Version(Map<K1, K2> first, Map<K2, V> second) { 
    HashMap<K1, V> result = new HashMap<>(Math.min(first.size(), second.size())); 
    for (Map.Entry<K1, K2> entry : first.entrySet()) { 
    if (second.containsKey(entry.getValue())) 
     result.put(entry.getKey(), second.get(entry.getValue())); 
    } 
    return result; 
} 

Ich glaube, ich auch wie die Java-7-Version besser, als es verständlicher und ehrlich über die Kosten ist.

Wenn Sie Schlüssel aus der ersten Karte halten wollen, auch wenn sie in der zweiten nicht vorhanden sind (oder die Option müssen), dann diese Versionen verwenden:

public static <K1, K2, V> Map<K1, V> java8VersionWithNulls(Map<K1, K2> first, Map<K2, V> second, boolean keepNulls) { 
    return first.entrySet() 
    .stream() 
    .filter(e -> keepNulls || second.containsKey(e.getValue())) 
    .collect(Collectors.toMap(Map.Entry::getKey, e -> second.get(e.getValue()))); 
} 

public static <K1, K2, V> Map<K1, V> java7VersionWithNulls(Map<K1, K2> first, Map<K2, V> second, boolean keepNulls) { 
    HashMap<K1, V> result = new HashMap<>(second.size()); 
    for (Map.Entry<K1, K2> entry : first.entrySet()) { 
    if (keepNulls || second.containsKey(entry.getValue())) 
     result.put(entry.getKey(), second.get(entry.getValue())); 
    } 
    return result; 
} 

Aber persönlich würde ich sagen, mach es nicht. Null ist böse.

Alle oben genannten verwenden eifrige Bewertung. Wenn Sie einen faulen Ansicht möchten, die Änderungen an den Karten verwenden Guava und etwas tun, wie dies widerspiegeln:

public static <K1, K2, V> Map<K1, V> guavaJava8Version(Map<K1, K2> first, Map<K2, V> second) { 
    return Maps.transformValues(
    Maps.filterKeys(first, Predicates.in(second.keySet())), 
    second::get); 
} 

oder mit statischer Importe:

public static <K1, K2, V> Map<K1, V> guavaJava8Version(Map<K1, K2> first, Map<K2, V> second) { 
    return transformValues(filterKeys(first, in(second.keySet())), second::get); 
} 

Die Karte zurück durch das sollte eine gute Leistung genug für Nachschlagevorgänge und Iterationen (konstante Zeit, wenn beide Hash-basiert sind), aber Sie sollten wahrscheinlich nicht size() darauf (oder einer der Sammlungen, die es zurückgibt) aufrufen.

+0

solides Zeug..danke! – labheshr

+0

Ein Detail: Warum filtern Sie Elemente nicht in der zweiten Karte? Sie könnten die Verknüpfung des Schlüssels mit dem Nullwert beibehalten, der von der zweiten Map zurückgegeben wird (die Filterung könnte zwar Sinn ergeben, wurde aber in der Frage nicht gestellt). – Thierry

+0

@Thierry Ich mag keine Nullwerte. Aber sicher, wenn Sie sie haben möchten, löschen Sie die Zeile mit dem Filter –

Verwandte Themen