2008-11-07 2 views
11

Ich bin auf der Suche nach einer Datenstruktur, die ähnlich wie eine Hash-Tabelle funktioniert, aber wo die Tabelle eine Größenbeschränkung hat. Wenn die Anzahl der Elemente im Hash die Größenbeschränkung erreicht, sollte eine Culling-Funktion aufgerufen werden, um die am wenigsten abgerufenen Schlüssel/Wert-Paare in der Tabelle zu entfernen.Wie sieht eine Datenstruktur aus wie eine Hash-Tabelle, aber selten verwendete Schlüssel werden gelöscht?

Hier einige Pseudo-Code von dem, was ich arbeite:

class MyClass { 
    private Map<Integer, Integer> cache = new HashMap<Integer, Integer>(); 
    public int myFunc(int n) { 
    if(cache.containsKey(n)) 
     return cache.get(n); 
    int next = . . . ; //some complicated math. guaranteed next != n. 
    int ret = 1 + myFunc(next); 
    cache.put(n, ret); 
    return ret; 
    } 
} 

Was passiert, ist, dass es einige Werte von n sind, für die myFunc() viele Male aufgerufen werden, aber viele andere Werte von n denen nur einmal berechnet werden. Der Cache könnte sich also mit Millionen von Werten füllen, die nie wieder benötigt werden. Ich hätte gerne eine Möglichkeit für den Cache, Elemente, die nicht häufig abgerufen werden, automatisch zu entfernen.

Das fühlt sich an wie ein Problem, das bereits gelöst werden muss, aber ich bin nicht sicher, was die Datenstruktur ist, die ich verwenden würde, um es effizient zu machen. Kann mir jemand in die richtige Richtung zeigen?


aktualisieren ich das wusste, dass ein bereits gelöstes Problem sein. Es wird als LRU-Cache bezeichnet und ist einfach zu erweitern, indem die Klasse LinkedHashMap erweitert wird. Hier ist der Code, der die Lösung enthält:

class MyClass { 
    private final static int SIZE_LIMIT = 1000; 
    private Map<Integer, Integer> cache = 
    new LinkedHashMap<Integer, Integer>(16, 0.75f, true) { 
     protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) 
     { 
     return size() > SIZE_LIMIT; 
     } 
    }; 
    public int myFunc(int n) { 
    if(cache.containsKey(n)) 
     return cache.get(n); 
    int next = . . . ; //some complicated math. guaranteed next != n. 
    int ret = 1 + myFunc(next); 
    cache.put(n, ret); 
    return ret; 
    } 
} 
+0

Siehe auch http://stackoverflow.com/questions/224868/easy-simple-to-use-lu-cache-in-java. –

Antwort

17

Sie suchen eine LRUList/Map suchen. Überprüfen :

Die removeEldestEntry(Map.Entry)-Methode kann überschrieben werden, um eine Richtlinie zum Entfernen von veralteten Zuordnungen automatisch aufzuerlegen, wenn neue Zuordnungen der Zuordnung hinzugefügt werden.

+0

Du hast mich dazu geschlagen ... –

+0

Danke, das war genau das, was ich wollte! – Kip

+0

Sie sind willkommen und es ist eine JDK-Klasse, also keine externen Abhängigkeiten. – ReneS

0

Werfen Sie einen Blick auf WeakHashMap

+0

Das ist nicht genau das, was ich will. Aus meiner Sicht bedeutet eine schwache Hash-Map, dass das Vorhandensein eines Schlüssels in der Map nicht als Referenz auf das Objekt gilt, sodass der Garbage Collector sie trotzdem entfernen kann. Da ich Integer verwende, kann ich nicht sicher sein, ob dies das macht, was ich möchte. – Kip

1

WeakHashMap wird wahrscheinlich nicht tun, was Sie erwarten, dass es ... lesen Sie die Dokumentation sorgfältig und stellen Sie sicher, dass Sie genau wissen, was du von schwachen und starken Referenzen hältst.

Ich würde empfehlen, schauen Sie sich java.util.LinkedHashMap an und verwenden Sie die Methode removeEldestEntry, um Ihren Cache zu verwalten. Wenn Ihre Mathematik sehr ressourcenintensiv ist, sollten Sie die Einträge immer nach vorne verschieben, wenn sie verwendet werden, um sicherzustellen, dass nur unbenutzte Einträge an das Ende des Satzes fallen.

4

googeln "LRU Karte" und "Auf gut Glück!" Gibt Ihnen dies:

http://commons.apache.org/proper/commons-collections//javadocs/api-release/org/apache/commons/collections4/map/LRUMap.html

A Map-Implementierung mit einer festen maximalen Größe, die den geringste zuletzt verwendeten Eintrag entfernt, wenn ein Eintrag ist hinzugefügt, wenn voll.

Klingt ziemlich viel Platz auf :)

+0

Danke, es war einer dieser Fälle, wo es wirklich einfach ist, die Antwort zu finden, wenn Sie bereits wissen, dass die Antwort "LRU-Karte" ist, aber wenn Sie bereits wussten, dass Sie es nicht finden müssten. :) – Kip

+0

Ja, tut mir leid, ich habe nicht versucht, snarky zu sein. Ich treffe zufällig auch "Ich fühle mich glücklich". –

1

Die Adaptive Replacement Cache Politik konzipiert einmalige Anfragen halten aus dem Cache zu verschmutzen. Das mag schicker sein, als Sie suchen, aber es spricht direkt Ihre "Füllung mit Werten an, die nie wieder gebraucht werden".

Verwandte Themen