1 16 package org.apache.commons.collections.map; 17 18 import java.io.IOException ; 19 import java.io.ObjectInputStream ; 20 import java.io.ObjectOutputStream ; 21 import java.io.Serializable ; 22 import java.util.Map ; 23 24 import org.apache.commons.collections.BoundedMap; 25 26 52 public class LRUMap 53 extends AbstractLinkedMap implements BoundedMap, Serializable , Cloneable { 54 55 56 static final long serialVersionUID = -612114643488955218L; 57 58 protected static final int DEFAULT_MAX_SIZE = 100; 59 60 61 private transient int maxSize; 62 63 private boolean scanUntilRemovable; 64 65 68 public LRUMap() { 69 this(DEFAULT_MAX_SIZE, DEFAULT_LOAD_FACTOR, false); 70 } 71 72 78 public LRUMap(int maxSize) { 79 this(maxSize, DEFAULT_LOAD_FACTOR); 80 } 81 82 90 public LRUMap(int maxSize, boolean scanUntilRemovable) { 91 this(maxSize, DEFAULT_LOAD_FACTOR, scanUntilRemovable); 92 } 93 94 103 public LRUMap(int maxSize, float loadFactor) { 104 this(maxSize, loadFactor, false); 105 } 106 107 118 public LRUMap(int maxSize, float loadFactor, boolean scanUntilRemovable) { 119 super((maxSize < 1 ? DEFAULT_CAPACITY : maxSize), loadFactor); 120 if (maxSize < 1) { 121 throw new IllegalArgumentException ("LRUMap max size must be greater than 0"); 122 } 123 this.maxSize = maxSize; 124 this.scanUntilRemovable = scanUntilRemovable; 125 } 126 127 136 public LRUMap(Map map) { 137 this(map, false); 138 } 139 140 151 public LRUMap(Map map, boolean scanUntilRemovable) { 152 this(map.size(), DEFAULT_LOAD_FACTOR, scanUntilRemovable); 153 putAll(map); 154 } 155 156 166 public Object get(Object key) { 167 LinkEntry entry = (LinkEntry) getEntry(key); 168 if (entry == null) { 169 return null; 170 } 171 moveToMRU(entry); 172 return entry.getValue(); 173 } 174 175 183 protected void moveToMRU(LinkEntry entry) { 184 if (entry.after != header) { 185 modCount++; 186 entry.before.after = entry.after; 188 entry.after.before = entry.before; 189 entry.after = header; 191 entry.before = header.before; 192 header.before.after = entry; 193 header.before = entry; 194 } 195 } 196 197 206 protected void updateEntry(HashEntry entry, Object newValue) { 207 moveToMRU((LinkEntry) entry); entry.setValue(newValue); 209 } 210 211 226 protected void addMapping(int hashIndex, int hashCode, Object key, Object value) { 227 if (isFull()) { 228 LinkEntry reuse = header.after; 229 boolean removeLRUEntry = false; 230 if (scanUntilRemovable) { 231 while (reuse != header) { 232 if (removeLRU(reuse)) { 233 removeLRUEntry = true; 234 break; 235 } 236 reuse = reuse.after; 237 } 238 } else { 239 removeLRUEntry = removeLRU(reuse); 240 } 241 242 if (removeLRUEntry) { 243 reuseMapping(reuse, hashIndex, hashCode, key, value); 244 } else { 245 super.addMapping(hashIndex, hashCode, key, value); 246 } 247 } else { 248 super.addMapping(hashIndex, hashCode, key, value); 249 } 250 } 251 252 263 protected void reuseMapping(LinkEntry entry, int hashIndex, int hashCode, Object key, Object value) { 264 int removeIndex = hashIndex(entry.hashCode, data.length); 268 HashEntry loop = data[removeIndex]; 269 HashEntry previous = null; 270 while (loop != entry) { 271 previous = loop; 272 loop = loop.next; 273 } 274 275 modCount++; 277 removeEntry(entry, removeIndex, previous); 278 reuseEntry(entry, hashIndex, hashCode, key, value); 279 addEntry(entry, hashIndex); 280 } 281 282 315 protected boolean removeLRU(LinkEntry entry) { 316 return true; 317 } 318 319 325 public boolean isFull() { 326 return (size >= maxSize); 327 } 328 329 334 public int maxSize() { 335 return maxSize; 336 } 337 338 345 public boolean isScanUntilRemovable() { 346 return scanUntilRemovable; 347 } 348 349 355 public Object clone() { 356 return super.clone(); 357 } 358 359 362 private void writeObject(ObjectOutputStream out) throws IOException { 363 out.defaultWriteObject(); 364 doWriteObject(out); 365 } 366 367 370 private void readObject(ObjectInputStream in) throws IOException , ClassNotFoundException { 371 in.defaultReadObject(); 372 doReadObject(in); 373 } 374 375 378 protected void doWriteObject(ObjectOutputStream out) throws IOException { 379 out.writeInt(maxSize); 380 super.doWriteObject(out); 381 } 382 383 386 protected void doReadObject(ObjectInputStream in) throws IOException , ClassNotFoundException { 387 maxSize = in.readInt(); 388 super.doReadObject(in); 389 } 390 391 } 392 | Popular Tags |