2016-04-20 8 views
1

Ich beginne lambda zu lernen, und ich verstehe nicht, warum Java-Karte hat:Karte getOrDefault VS getOrUseSupplier

getOrDefault(Object key, V defaultValue) 

und nicht (Arbeits genau die gleichen, aber wenn der Wert nicht vorhanden ist, dann wird default aus genommen werden Lieferant):

getOrUseSupplier(Object key, Supplier<V> defaultValue) 

adventages i zur Zeit der aktuellen Lösung sehen:

  • default muss nicht eine endgültige/e sein ffectively Endwert
  • sieht einfacher & keine Notwendigkeit, Lambda-Syntax

Disadventages zu wissen:

  • Wenn bei der Verwendung von getOrDefault wir neue Objekterstellung setzen, wird es erstellt und weitergegeben werden immidietely GC (während Wenn Sie einen Lieferanten verwenden, wird dieser überhaupt nicht erstellt).

Ich würde gerne wissen, ob es noch mehr disadventages der Verwendung & mit getOrDefault ist eher als getOrUseSupplier. Könnten Sie mir sagen, auch wenn überall in Java-Bibliotheken gibt Methode ist wie folgt:

static <V> V getOrUseSupplier(Map<?, V> map, Object key, Supplier<V> supplier) 

, den Wert von Karte zu nehmen versucht, und wenn nicht, dann nimmt vom Lieferanten Wert nicht vorhanden ist.

+0

Im 'getOrUserSupplier' Fall Sie noch ein' Supplier' Objekt erstellen, das GCed sein muss. Die einzigen Kosten, die Sie gegenüber 'getOrDefault' sparen, ist das Ausführen von' V's Konstruktor (wenn das erhebliche Kosten verursacht). – sepp2k

+0

Können Sie mir sagen, wie viel Speicher jedes Mal benötigt wird, um einen Lieferanten zu erstellen, wenn eine Methode aufgerufen wird? – user3009344

+0

@ sepp2k Erzeugt es wirklich einen neuen Lieferanten? Soll es nicht zu einem statischen Methodenaufruf kompiliert werden, was bedeutet, dass nur eine Instanz des Lieferanten erstellt wird? – Kayaman

Antwort

1

Der nächste Äquivalent von getOrUseSupplier() in Map ist computeIfAbsent() benannt, die für den Wert ermöglicht es den Schlüssel berechnet wird unter Verwendung, als mehr Flexibilität, wenn es dauert nur ein Supplier. Es speichert auch den berechneten Wert in der Map, im Gegensatz zu getOrDefault. Dies liegt daran, dass sie unterschiedliche Anwendungsfälle haben und nicht wirklich verwandt sind. Während getOrDefault normalerweise verwendet wird, um einen "sicheren" Nicht-Null-Standardwert (z. B. die Rückgabe einer leeren Zeichenfolge statt einer Null) zurückzugeben, der angibt, dass sich in der Karte befinden sollte, bedeutet computeIfAbsent(), dass sich in der Karte befinden muss. und wenn es nicht ist, muss es erstellt werden oder andernfalls ist der interne Zustand des Programms nicht korrekt.

Das folgende Beispiel ignoriert den Schlüssel und verwendet nur den Wert des Lieferanten.

public static <V,T> V getOrUseSupplier(Map<T, V> map, T key, Supplier<V> supplier) { 
    return map.computeIfAbsent(key, k -> supplier.get()); 
} 
+7

Beachten Sie, dass "computeIfAbsent" den berechneten Wert in die Map eingibt, während "getOrDefault" keine Nebenwirkungen hat. –

+0

Ja, das ist ** nicht ** äquivalent, da 'getOrDefault' die Map nicht ändert, während' computeIfAbsent' dies tut. –

+0

@ ChristofferHammarström Herausgegeben, um den Unterschied zu enthalten. – Kayaman

1

Ich vermute es lag daran, die Map-Schnittstelle nicht zu sprengen. Sie können Optional.orElseGet(Supplier) als Abhilfe verwenden (wenn Sie in der Karte nicht NULL-Werte halten):

Optional.ofNullable(map.get(key)).orElseGet(supplier)