1 21 package org.lobobrowser.util; 22 23 import java.util.*; 24 25 29 public class LRUCache implements java.io.Serializable { 30 private static final long serialVersionUID = 940427225784212823L; 31 private final int approxMaxSize; 32 private final Map cacheMap = new HashMap(); 33 34 37 private final TreeSet timedSet = new TreeSet(); 38 private int currentSize = 0; 39 40 public LRUCache(int approxMaxSize) { 41 this.approxMaxSize = approxMaxSize; 42 } 43 44 public void put(Object key, Object value, int approxSize) { 45 if(approxSize > this.approxMaxSize) { 46 throw new IllegalArgumentException ("Max size is " + this.approxMaxSize); 47 } 48 OrderedValue ordVal = (OrderedValue) this.cacheMap.get(key); 49 if(ordVal != null) { 50 this.currentSize += (approxSize - ordVal.approximateSize); 51 this.timedSet.remove(ordVal); 52 ordVal.approximateSize = approxSize; 53 ordVal.value = value; 54 ordVal.touch(); 55 this.timedSet.add(ordVal); 56 } 57 else { 58 ordVal = new OrderedValue(value, approxSize); 59 this.cacheMap.put(key, ordVal); 60 this.timedSet.add(ordVal); 61 this.currentSize += approxSize; 62 } 63 while(this.currentSize > this.approxMaxSize) { 64 this.removeLRU(); 65 } 66 } 67 68 private void removeLRU() { 69 OrderedValue ordVal = (OrderedValue) this.timedSet.first(); 70 if(ordVal != null) { 71 if(this.timedSet.remove(ordVal)) { 72 this.currentSize -= ordVal.approximateSize; 73 } 74 else { 75 throw new IllegalStateException ("Could not remove existing tree node."); 76 } 77 } 78 else { 79 throw new IllegalStateException ("Cannot remove LRU since the cache is empty."); 80 } 81 } 82 83 public Object get(Object key) { 84 OrderedValue ordVal = (OrderedValue) this.cacheMap.get(key); 85 if(ordVal != null) { 86 this.timedSet.remove(ordVal); 87 ordVal.touch(); 88 this.timedSet.add(ordVal); 89 return ordVal.value; 90 } 91 else { 92 return null; 93 } 94 } 95 96 private class OrderedValue implements Comparable , java.io.Serializable { 97 private static final long serialVersionUID = 340227625744215821L; 98 private long timestamp; 99 private int approximateSize; 100 private Object value; 101 102 private OrderedValue(Object value, int approxSize) { 103 this.value = value; 104 this.approximateSize = approxSize; 105 this.touch(); 106 } 107 108 private final void touch() { 109 this.timestamp = System.currentTimeMillis(); 110 } 111 112 public int compareTo(Object arg0) { 113 if(this == arg0) { 114 return 0; 115 } 116 OrderedValue other = (OrderedValue) arg0; 117 long diff = this.timestamp - other.timestamp; 118 if(diff != 0) { 119 return (int) diff; 120 } 121 int hc1 = System.identityHashCode(this); 122 int hc2 = System.identityHashCode(other); 123 if(hc1 == hc2) { 124 hc1 = System.identityHashCode(this.value); 125 hc2 = System.identityHashCode(other.value); 126 } 127 return hc1 - hc2; 128 } 129 } 130 } 131 | Popular Tags |