2012-06-11 4 views
7

Ich bin nicht gewöhnt, mit weichen und schwachen Referenzen in Java umzugehen, aber ich verstehe das Prinzip, da ich mit Datagrids wie Gemfire umgehen kann, die einen Überlauf zu HDD Features bieten Speicher ist voll, wahrscheinlich mit weichen Referenzen oder etwas ähnliches, denke ich.Guava CacheBuilder oder MapMaker mit schwachem/weichem Verbrauch

Was ich in Guava nicht verstehe, ist, dass es Methoden zur Verfügung stellt, um die Schlüssel weich/schwach und die Werte weich/schwach zu machen.

Ich frage mich nur, was ist der Punkt der Erstellung von Softkeys mit nicht-weichen Werten für Beispiel? Ich meine, wenn die Soft-Referenzen gesammelt werden, können wir den Eintrag nicht mehr mit seinem Schlüssel finden. Warum sollten wir also die Werte auf der Karte behalten?

Kann jemand gibt uns einige usecases mit:

  • Schwachen Schlüssel/Soft-Wert
  • Schwachen Schlüssel/Normalwert
  • Softkey/schwachen Wert
  • Softkey/Normalwert

Dank

bearbeiten Ich bin nicht sicher, ob meine Frage präzise genug so, was ich wissen möchte:

  • , wenn eine Taste (schwach/weich) gesammelt wird, was dem Wert passiert, (nicht schwach/weich)
  • Wenn ein Wert erfasst wird (schwach/weich), was passiert mit dem Schlüssel
  • Werden Einträge mit einem fehlenden Teil (Schlüssel oder Wert) im Cache gespeichert?
  • Und gibt es einen Anwendungsfall, wenn solche Einträge im Cache bleiben sollen.

Edit: Wie auf Kevin Bourillon Antwort diskutiert, schließlich ich glaube, ich verstehe, warum Softkeys hat nichts zu bedeuten. Hier ist der Grund:

TESTING WEAK KEYS 
strongRefKey = strongRef 
noStrongRefKey = null 
keyset = [KeyHolder{key='toto'}] 



TESTING SOFT KEYS 
strongRefKey = strongRef 
noStrongRefKey = null 
keyset = [KeyHolder{key='tata'}, KeyHolder{key='toto'}] 



TESTING SOFT REFERENCES 
toto == toto -> true 
equals keys? true 
equals ref? false 

Wie Sie sehen können, mit der (veraltet) Softkeys Karte, die KEYHOLDER mit "tata" noch existieren in der Karte:

static class KeyHolder { 
    final private String key; 
    public KeyHolder(String key) { 
     this.key = key; 
    } 
    public String getKey() { 
     return key; 
    } 
    @Override 
    public boolean equals(Object o) { 
     KeyHolder that = (KeyHolder)o; 
     boolean equality = this.getKey().equals(that.getKey()); 
     return equality; 
    } 
    @Override 
    public int hashCode() { 
     return key != null ? key.hashCode() : 0; 
    } 
    @Override 
    public String toString() { 
     return "KeyHolder{" + 
       "key='" + key + '\'' + 
       '}'; 
    } 
} 

public static void main(String[] args) { 
    System.out.println("TESTING WEAK KEYS"); 
    testMap(new MapMaker().weakKeys().<KeyHolder,String>makeMap()); 


    System.out.println("\n\n"); 
    System.out.println("TESTING SOFT KEYS"); 
    testMap(new MapMaker().softKeys().<KeyHolder, String>makeMap()); 


    System.out.println("\n\n"); 
    System.out.println("TESTING SOFT REFERENCES"); 
    KeyHolder key1 = new KeyHolder("toto"); 
    KeyHolder key2 = new KeyHolder("toto"); 
    SoftReference<KeyHolder> softRef1 = new SoftReference<KeyHolder>(key1); 
    SoftReference<KeyHolder> softRef2 = new SoftReference<KeyHolder>(key2); 
    System.out.println("equals keys? " + key1.equals(key2)); 
    System.out.println("equals ref? " + softRef1.equals(softRef2)); 
} 

private static void testMap(Map<KeyHolder,String> map) { 
    KeyHolder strongRefKey = new KeyHolder("toto"); 
    KeyHolder noStrongRefKey = new KeyHolder("tata"); 
    map.put(strongRefKey,"strongRef"); 
    map.put(noStrongRefKey,"noStrongRefKey"); 
    // we replace the strong reference by another key instance which is equals 
    // this could happen for exemple in case of serialization/deserialization of the key 
    noStrongRefKey = new KeyHolder("tata"); 
    System.gc(); 
    System.out.println("strongRefKey = " + map.get(strongRefKey)); 
    System.out.println("noStrongRefKey = " + map.get(noStrongRefKey)); 
    System.out.println("keyset = " + map.keySet()); 
} 

Dieser Code die Ausgabe erzeugt. Beachten Sie jedoch, dass ich meinen Eintrag mit einem neu erstellten Schlüssel "new KeyHolder("tata");" immer noch nicht finden kann. Das liegt daran, dass meine Schlüssel sinngemäß gleich sind, aber die Referenzwrapper um sie herum nicht gleich sind, da ihre equals-Methode nicht überschrieben wird in Guava! In diesem Fall, ja, SoftKeys bedeutet nichts, da Sie unbedingt eine Identitätsverweis auf diesen Schlüssel halten müssen, um es abrufen zu können.

Antwort

13

softKeys macht nie Sinn, also haben wir die Methode entfernt. softValues ist die einzige Möglichkeit, weiche Refs sinnvoll zu machen, wenn man davon ausgeht, dass die Wert-Instanzen auch außerhalb des Cache nicht erreichbar sind.

Die Verwendung von weakKeys läuft im Grunde darauf hinaus, ob Sie Identitätsgleichheit für Schlüssel wollen. Wenn der Schlüssel equals überschreibt und Sie das Gleichheitsverhalten benötigen, können Sie es nicht verwenden. Wenn Sie Identität wollen, dann ist weakKeys, wie Sie das bekommen, und es macht auch Sinn, weil, sobald alle anderen Verweise auf den Schlüssel GC'd wurden, es keine Möglichkeit geben würde, diesen Eintrag trotzdem nachzuschlagen, so könnte es auch sein entfernt.

Ich bin eigentlich nicht ganz klar auf, wenn weakValues ist nützlich, und würde nachschauen. Es wäre wahrscheinlich ein Fall, in dem weakKeys keine Option ist (zB Integer Schlüssel), und wo die Werte normalerweise durch andere Mittel, wie eine Art von Sitzungsobjekt referenziert werden, aber wenn das Objekt verschwindet, bedeutet dies niemand wird mehr im Cache nach diesem suchen. Es scheint etwas weit hergeholt, wenn ich es so sage.

+0

Wenn Sie also Softvalues ​​verwenden und die meisten Werte gesammelt werden, haben Sie immer noch einen Cache mit vielen Einträgen, vielen Schlüsseln, aber keinen Wert? –

+1

Wenn Sie also schwache Schlüssel verwenden und die Schlüssel nicht mehr außerhalb des Caches stehen, werden die Schlüssel gesammelt, aber was passiert mit den Werten? Werden sie im Cache aufbewahrt? –

+1

Wenn du sagst, dass SoftKeys keinen Sinn ergeben, bin ich mir nicht sicher. Was ist, wenn Sie die Möglichkeit haben, einen neuen Schlüssel zu rekonstruieren: Sie möchten vielleicht, dass die Schlüssel im Cache bleiben, auch wenn Sie keine Identitätsreferenz haben, da Sie den entsprechenden Schlüssel NEIN erneut erstellen können? Was ist mit dem Schlüssel, der geklont/serialisiert/deserialisiert wird? Siehst du, was ich meine? –

2

Die Nicht-Guava WeakHashMap basiert auf schwachen Schlüsseln und verwirft den gesamten Eintrag, wenn ein Schlüssel nicht mehr verwendet wird. Somit gibt es keinen "Wert, der in der Karte bleibt".Dies ist die Art von Verhalten, die ich intuitiv von einer solchen Datenstruktur erwarten würde, und ich vermute stark, dass sich Guava auf die gleiche Weise verhält, auch für gesammelte weiche Referenzen. Beachten Sie, dass die Java Collections-Bibliothek nur eine schwache Schlüssel/Normalwerte-Map bietet, keine schwachen Keys/Soft-Werte oder schwache Keys/Weak-Werte, da der Benutzer den Wert selbst wickeln kann (aber nicht mit den Schlüsseln) da erwartet werden kann, dass das Nachschlagen in einer Hashmap für die tatsächlichen Schlüssel und schwachen Referenzen auf die Schlüssel nicht gleich funktioniert.

Ich selbst benutzte einmal eine WeakHashMap, um Objekte zu assoziieren, die durch einen Mechanismus veraltet werden könnten, mit Informationen, die nichts mit diesem Mechanismus zu tun haben (um genau zu sein: bewegte Bälle, die durch bestimmte Kollisionen zerstört werden könnten mit Informationen zu ihrer letzten Bewegung). Diese Werte wurden speziell für diese Map erstellt und nicht an anderer Stelle referenziert (außer lokal in Methoden, die nur aufgerufen werden konnten, während ihre Schlüssel noch existierten). Daher war es nicht notwendig, etwas anderes als normale Verweise auf die Werte zu verwenden, da der Wert, wenn der Schlüssel veraltet wurde, nicht mehr referenziert und unbrauchbar werden würde.

+1

Beachten Sie, dass bei Verwendung von schwachen Schlüsseln ein Vorbehalt besteht: "Warnung: Wenn diese Methode [weakKey()] verwendet wird, verwendet der resultierende Cache einen Identitätsvergleich (==), um die Gleichheit der Schlüssel zu bestimmen." – thSoft

Verwandte Themen