1 16 package org.apache.taglibs.cache; 17 18 import java.util.*; 19 20 35 public class LRUCache { 36 37 40 public static void main(String args[]) throws Exception { 41 LRUCache m = 42 new LRUCache(Integer.parseInt(args[0]), Integer.parseInt(args[1])); 43 String line; 44 java.io.BufferedReader r = 45 new java.io.BufferedReader (new java.io.InputStreamReader (System.in)); 46 while ((line = r.readLine()) != null) { 47 m.put(line, line); 48 Iterator i = m.keySet().iterator(); 49 System.out.println(" size = " + m.getCurrentSize()); 50 while (i.hasNext()) 51 System.out.println(" -> " + i.next()); 52 } 53 } 54 55 58 private Map cache = new HashMap(); 59 private LinkedList lruList = new LinkedList(); 60 private int currentSize = 0, maxSize; 61 private int lifetime; 62 63 64 67 70 private class CacheEntry { 71 private long expiration; 72 private String value; 73 private int size; 74 75 public CacheEntry(String value) { 76 this.value = value; 77 this.size = value.length(); 78 if (lifetime > 0) { 79 this.expiration = (new Date()).getTime() + lifetime; 80 } 81 } 82 public String getValue() { return value; } 83 public long getSize() { return size; } 84 public boolean isExpired() { 85 if (lifetime <= 0) 86 return false; 87 return (expiration < (new Date()).getTime()); 88 } 89 } 90 91 92 95 public void clear() { 96 cache = new HashMap(); 97 lruList = new LinkedList(); 98 } 99 100 public String get(Object key) { 101 if (currentSize > maxSize) 103 throw new AssertionError ("cache state corrupted"); 104 105 CacheEntry e = (CacheEntry) cache.get(key); 106 if (e == null) { 107 return null; 108 } else if (e.isExpired()) { 109 cache.remove(key); 111 lruList.remove(key); 112 currentSize -= e.getSize(); 113 return null; 114 } else { 115 noteUsed(key); 116 return ((CacheEntry) cache.get(key)).getValue(); 117 } 118 } 119 120 public Object put(Object key, Object value) { 121 if (!(value instanceof String )) 122 throw new IllegalArgumentException ( 123 "this Map only accepts Strings as values"); 124 125 CacheEntry oldEntry = (CacheEntry) cache.get(key); 126 if (oldEntry != null) 127 currentSize -= oldEntry.getSize(); 128 CacheEntry e = new CacheEntry((String ) value); 129 currentSize += e.getSize(); 130 cache.put(key, e); 131 noteUsed(key); 132 133 if (currentSize > maxSize) { 134 removeExpired(); 135 136 while (currentSize > maxSize) { 138 CacheEntry doomedEntry = (CacheEntry) cache.remove(lruList.getLast()); 139 lruList.removeLast(); 140 currentSize -= doomedEntry.getSize(); 141 } 142 143 if (currentSize > maxSize) 145 throw new AssertionError ("cache state corrupted"); 146 } 147 148 if (oldEntry == null || oldEntry.isExpired()) 150 return null; 151 else 152 return oldEntry.getValue(); 153 } 154 155 public Object remove(Object key) { 156 lruList.remove(key); 157 158 CacheEntry oldEntry = (CacheEntry) cache.remove(key); 160 if (oldEntry != null) 161 currentSize -= oldEntry.getSize(); 162 if (oldEntry == null || oldEntry.isExpired()) 163 return null; 164 else 165 return oldEntry.getValue(); 166 } 167 168 public Set keySet() { 169 removeExpired(); 170 return cache.keySet(); 171 } 172 173 176 public int getCurrentSize() { 177 return currentSize; 178 } 179 180 183 188 public LRUCache(int size, int lifetime) { 189 this.maxSize = size; 190 this.lifetime = lifetime * 1000; 191 } 192 193 194 197 198 private void noteUsed(Object key) { 199 lruList.remove(key); 200 lruList.addFirst(key); 201 } 202 203 private void removeExpired() { 204 if (lifetime >= 0) { 206 Iterator i = cache.entrySet().iterator(); 208 while (i.hasNext()) { 209 Map.Entry ent = (Map.Entry) i.next(); 210 CacheEntry testEntry = (CacheEntry) ent.getValue(); 211 if (testEntry.isExpired()) { 212 i.remove(); 213 lruList.remove(ent.getKey()); 214 currentSize -= testEntry.getSize(); 215 } 216 } 217 } 218 } 219 } 220 | Popular Tags |