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++; } }