package btools.util; /** * Something like LinkedHashMap, but purpose build, less dynamic and memory efficient * * @author ab */ public final class LruMap { private int hashbins; private int maxsize; private int size; private LruMapNode lru; private LruMapNode mru; private LruMapNode[] binArray; public LruMap(int bins, int size) { hashbins = bins; maxsize = size; binArray = new LruMapNode[hashbins]; } public LruMapNode get(LruMapNode key) { int bin = (key.hash & 0xfffffff) % hashbins; LruMapNode e = binArray[bin]; while (e != null) { if (key.equals(e)) { return e; } e = e.nextInBin; } return null; } // put e to the mru end of the queue public void touch(LruMapNode e) { LruMapNode n = e.next; LruMapNode p = e.previous; if (n == null) { return; // already at mru } n.previous = p; if (p != null) { p.next = n; } else { lru = n; } mru.next = e; e.previous = mru; e.next = null; mru = e; } public LruMapNode removeLru() { if (size < maxsize) { return null; } size--; // unlink the lru from it's bin-queue int bin = (lru.hashCode() & 0xfffffff) % hashbins; LruMapNode e = binArray[bin]; if (e == lru) { binArray[bin] = lru.nextInBin; } else { while (e != null) { LruMapNode prev = e; e = e.nextInBin; if (e == lru) { prev.nextInBin = lru.nextInBin; break; } } } LruMapNode res = lru; lru = lru.next; lru.previous = null; return res; } public void put(LruMapNode val) { int bin = (val.hashCode() & 0xfffffff) % hashbins; val.nextInBin = binArray[bin]; binArray[bin] = val; val.previous = mru; val.next = null; if (mru == null) { lru = val; } else { mru.next = val; } mru = val; size++; } }