brouter/brouter-util/src/main/java/btools/util/LruMap.java
2018-12-16 13:32:16 +01:00

121 lines
2 KiB
Java

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