Java LRU (least recently Used) detailed
LRU is least recently Used abbreviation, translation is "least recently used", the LRU cache is the use of this principle to achieve, simply to cache a certain amount of data, when more than the set threshold to delete some outdated data, such as we cache 10,000 of data, When the data is less than 10000, you can add it randomly. When more than 10000 of the need to add new data, and to delete the outdated data to ensure that we have the largest cache of 10,000, then how to determine the deletion of the expired data, the use of LRU algorithm is the oldest data deleted, nonsense not to say, The following Java version of the LRU cache implementation
Java inside the implementation of LRU cache usually have two choices, one is to use Linkedhashmap, one is to design their own data structure, using the linked list +hashmap
Linkedhashmap implementation of LRU cache
The LINKEDHASHMAP itself has implemented sequential storage by default, stored in the order in which the elements are added, or enabled in the order of access, where the most recently read data is at the front, the oldest read is on the last side, and then it has a way of determining whether to delete the oldest data. The default is to return False, that is, do not delete data, we use Linkedhashmap to implement LRU caching method is to achieve a simple linkedhashmap extension, there are two ways to expand, one is inheritance, one is delegation, What is the specific way to see a person's preferences
A constructor of the linkedhashmap that, when the argument Accessorder is true, is sorted according to the access order, most recently accessed, and the first access is placed behind the public
linkedhashmap (int Initialcapacity, Float loadfactor, Boolean accessorder) {
super (initialcapacity, loadfactor);
This.accessorder = Accessorder;
}
Linkedhashmap to determine whether to delete the oldest element method, the default return False, that is, do not delete old data
//What we have to do is rewrite this method to delete old data when certain conditions are met
protected Boolean Removeeldestentry (map.entry<k,v> eldest) {return
false;
}
LRU Cache Linkedhashmap (inheritance) implementation
The implementation of the inheritance method is simpler, and the map interface is implemented, and the Collections.synchronizedmap () method can be used to implement the thread-safe operation in the multi-threaded environment.
Package CN.LZRABBIT.STRUCTURE.LRU;
Import Java.util.LinkedHashMap;
Import Java.util.Map;
/**
* Created by Liuzhao on 14-5-15.
* * Public
class lrucache2<k, v> extends Linkedhashmap<k, v> {
private final int max_cache_size;
Public LRUCache2 (int cacheSize) {
super ((int) Math.ceil (cachesize/0.75) + 1, 0.75f, true);
Max_cache_size = cacheSize;
}
@Override
protected Boolean removeeldestentry (Map.entry eldest) {return
size () > max_cache_size;
}
@Override public
String toString () {
StringBuilder sb = new StringBuilder ();
For (Map.entry<k, v> entry:entryset ()) {
sb.append (String.Format ("%s:%s", Entry.getkey (), Entry.getvalue ( )));
}
return sb.tostring ();
}
This is compared to the implementation of the standard, the actual use of this writing is still a bit cumbersome, more practical methods like the following write, eliminating the trouble of seeing a class alone
Final int cacheSize = m;
map<string, string> map = new linkedhashmap<string, string> ((int) Math.ceil (cachesize/0.75f) + 1, 0.75f, Tru e) {
@Override
protected Boolean removeeldestentry (Map.entry<string, string> eldest) {return
size ( ) > cacheSize;
}
;
LRU Cache Linkedhashmap (delegation) implementation
The delegation approach is more elegant, but because the map interface is not implemented, thread synchronization needs to be done by itself
Package CN.LZRABBIT.STRUCTURE.LRU;
Import Java.util.LinkedHashMap;
Import Java.util.Map;
Import Java.util.Set;
/** * Created by Liuzhao on 14-5-13.
* * public class lrucache3<k, v> {private final int max_cache_size;
Private final float default_load_factor = 0.75f;
Linkedhashmap<k, v> map;
Public LRUCache3 (int cacheSize) {max_cache_size = cacheSize; The HashMap capactiy,+1 is calculated according to the CacheSize and load factors to ensure that hashmap expansion is not triggered when the CacheSize upper limit is reached, int capacity = (int) Math.ceil (max_cache_
Size/default_load_factor) + 1; Map = new Linkedhashmap (capacity, Default_load_factor, true) {@Override protected Boolean removeeldestentry (M Ap.
Entry eldest) {return size () > max_cache_size;
}
};
synchronized void put (K key, V value) {map.put (key, value);
Public synchronized V get (K key) {return map.get (key);
Public synchronized void Remove (K key) {map.remove (key); } Public Synchronized set<map.entry&Lt
K, v>> GetAll () {return map.entryset ();
public synchronized int size () {return map.size ();
Public synchronized void Clear () {map.clear ();
@Override public String toString () {StringBuilder sb = new StringBuilder ();
For (Map.entry Entry:map.entrySet ()) {Sb.append (String.Format ("%s:%s", Entry.getkey (), Entry.getvalue ()));
return sb.tostring ();
}
}
+HASHMAP realization of LRU Cache's linked list
Note: This implementation is not thread-safe, and if used in a multithreaded environment, you need to add synchronized on related methods to implement thread-safe operations
Package CN.LZRABBIT.STRUCTURE.LRU;
Import Java.util.HashMap;
/** * Created by Liuzhao on 14-5-12.
* * public class lrucache1<k, v> {private final int max_cache_size;
Private Entry;
Private Entry last;
Private Hashmap<k, entry<k, v>> HashMap;
Public LRUCache1 (int cacheSize) {max_cache_size = cacheSize;
HashMap = new Hashmap<k, entry<k, v>> ();
public void put (K key, V value) {Entry Entry = getentry (key);
if (entry = = null) {if (Hashmap.size () >= max_cache_size) {hashmap.remove (Last.key);
Removelast ();
} entry = new entry ();
Entry.key = key;
} entry.value = value;
Movetofirst (entry);
Hashmap.put (key, entry);
Public V get (K key) {entry<k, v> Entry = Getentry (key);
if (entry = null) return null;
Movetofirst (entry);
return entry.value;
public void Remove (K key) {Entry Entry = getentry (key); If (Entry!= nuLL) {if (entry.pre!= null) Entry.pre.next = Entry.next;
if (entry.next!= null) Entry.next.pre = Entry.pre;
if (entry = = Entry.next;
if (entry = last) last = Entry.pre;
} hashmap.remove (key);
private void Movetofirst (Entry Entry) {if (Entry = = i) return;
if (entry.pre!= null) Entry.pre.next = Entry.next;
if (entry.next!= null) Entry.next.pre = Entry.pre;
if (entry = last) last = Last.pre;
if (i = null | | | last = NULL) {a = last = entry;
Return
} entry.next = i;
First.pre = entry;
i = entry;
Entry.pre = null;
private void Removelast () {if (last!= null) {last = Last.pre;
if (last = = null) a = NULL;
else Last.next = null;
} private Entry<k, v> getentry (K key) {return hashmap.get (key);
@Override public String toString () {StringBuilder sb = new StringBuilder (); Entry Entry = FirsT
while (entry!= null) {Sb.append (String.Format ("%s:%s", Entry.key, Entry.value));
Entry = Entry.next;
return sb.tostring ();
Class Entry<k, v> {public Entry pre;
Public Entry Next;
Public K key;
public V value;
}
}
FIFO implementation of Linkedhashmap
FIFO is first Input initial output abbreviation, also is commonly said to precede first out, by default Linkedhashmap is saved in the order of addition, we only need to rewrite the next Removeeldestentry method can easily implement a FIFO cache , the simplified version of the implementation code is as follows
Final int cacheSize = 5;
Linkedhashmap<integer, string> LRU = new Linkedhashmap<integer, string> () {
@Override
protected Boolean removeeldestentry (Map.entry<integer, string> eldest) {return
size () > cacheSize;
}
};
Call Example
Package CN.LZRABBIT.STRUCTURE.LRU;
Import Cn.lzrabbit.ITest;
Import Java.util.LinkedHashMap;
Import Java.util.Map;
/** * Created by Liuzhao on 14-5-15. */public class Lrucachetest {public static void main (string[] args) throws Exception {System.out.println ("start.
..");
LruCache1 ();
LruCache2 ();
LruCache3 ();
LruCache4 ();
System.out.println ("over ...");
static void LruCache1 () {System.out.println ();
System.out.println ("===========================LRU linked list realization ===========================");
Lrucache1<integer, string> LRU = new LRUCache1 (5);
Lru.put (1, "11");
Lru.put (2, "11");
Lru.put (3, "11");
Lru.put (4, "11");
Lru.put (5, "11");
System.out.println (Lru.tostring ());
Lru.put (6, "66");
Lru.get (2);
Lru.put (7, "77");
Lru.get (4);
System.out.println (Lru.tostring ());
System.out.println ();
} static <T> void LruCache2 () {System.out.println (); System.out.println ("===========================lru Linkedhashmap (inheritance) to achieve =========================== ");
Lrucache2<integer, string> LRU = new LRUCache2 (5);
Lru.put (1, "11");
Lru.put (2, "11");
Lru.put (3, "11");
Lru.put (4, "11");
Lru.put (5, "11");
System.out.println (Lru.tostring ());
Lru.put (6, "66");
Lru.get (2);
Lru.put (7, "77");
Lru.get (4);
System.out.println (Lru.tostring ());
System.out.println ();
static void LruCache3 () {System.out.println ();
System.out.println ("===========================lru Linkedhashmap (delegation) to achieve ===========================");
Lrucache3<integer, string> LRU = new LRUCache3 (5);
Lru.put (1, "11");
Lru.put (2, "11");
Lru.put (3, "11");
Lru.put (4, "11");
Lru.put (5, "11");
System.out.println (Lru.tostring ());
Lru.put (6, "66");
Lru.get (2);
Lru.put (7, "77");
Lru.get (4);
System.out.println (Lru.tostring ());
System.out.println (); } static void LruCache4 () {System. OUT.PRINTLN ();
System.out.println ("===========================fifo linkedhashmap default implementation ===========================");
Final int cacheSize = 5; Linkedhashmap<integer, string> LRU = new Linkedhashmap<integer, string> () {@Override protected Bo
Olean Removeeldestentry (Map.entry<integer, string> eldest) {return size () > cacheSize;
}
};
Lru.put (1, "11");
Lru.put (2, "11");
Lru.put (3, "11");
Lru.put (4, "11");
Lru.put (5, "11");
System.out.println (Lru.tostring ());
Lru.put (6, "66");
Lru.get (2);
Lru.put (7, "77");
Lru.get (4);
System.out.println (Lru.tostring ());
System.out.println ();
}
}
Run results
"C:\Program Files (x86) \java\jdk1.6.0_10\bin\java"-didea.launcher.port=7535 "-didea.launcher.bin.path=c:\program Files (x86) \jetbrains\intellij idea 13.0.2\bin "-dfile.encoding=utf-8-classpath" C:\Program Files (x86) \java\jdk1.6.0 _10\jre\lib\charsets.jar; C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\deploy.jar; C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\javaws.jar; C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\jce.jar; C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\jsse.jar; C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\management-agent.jar; C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\plugin.jar; C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\resources.jar; C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\rt.jar; C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\ext\dnsns.jar; C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\ext\localedata.jar; C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\ext\sunjce_provider.jar; C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\ext\sunmscapi.jaR C:\Program Files (x86) \java\jdk1.6.0_10\jre\lib\ext\sunpkcs11.jar;d:\svn\projects\java\java.algorithm\target\ test-classes;d:\svn\projects\java\java.algorithm\target\classes; C:\Program Files (x86) \jetbrains\intellij idea 13.0.2\lib\idea_rt.jar " Com.intellij.rt.execution.application.AppMain Main start ... ===========================lru linked list realization =================== ========
5:11 4:11 3:11 2:11 1:11
4:11 7:77 2:11 6:66 5:11
===========================LRU LinkedHashMap(inheritance)实现 =========================== 1:11 2:11 3:11 4:11 5:11 5:11 6:66 2:11 7:77 4:11 ===========================lru LinkedHas Hmap (delegation) Implementation =========================== 1:11 2:11 3:11 4:11 5:11 5:11 6:66 2:11 7:77 4:11 ====================== =====fifo Linkedhashmap Default implementation =========================== {1=11, 2=11, 3=11, 4=11, 5=11} {3=11, 4=11, 5=11, 6=66, 7=77} over
...
Process finished with exit code 0
Thank you for reading, I hope to help you, thank you for your support for this site!