1 29 33 package net.matuschek.util; 34 35 import java.util.Enumeration ; 36 import java.util.Hashtable ; 37 38 52 53 public class LruHashtable extends Hashtable 54 { 55 56 private static final int nBuckets = 2; 58 59 private float loadFactor; 61 62 private int threshold; 64 65 private int eachCapacity; 67 68 private Hashtable oldTable; 70 private Hashtable newTable; 71 72 public LruHashtable( int initialCapacity, float loadFactor ) 84 { 85 super( 1 ); 90 91 if ( initialCapacity <= 0 || loadFactor <= 0.0 ) 92 throw new IllegalArgumentException (); 93 this.loadFactor = loadFactor; 94 threshold = (int) ( initialCapacity * loadFactor ) - 1; 95 eachCapacity = initialCapacity / nBuckets + 1; 96 oldTable = new Hashtable ( eachCapacity, loadFactor ); 97 newTable = new Hashtable ( eachCapacity, loadFactor ); 98 } 99 100 public LruHashtable( int initialCapacity ) 106 { 107 this( initialCapacity, 0.75F ); 108 } 109 110 public int size() 112 { 113 return newTable.size() + oldTable.size(); 114 } 115 116 public boolean isEmpty() 118 { 119 return size() == 0; 120 } 121 122 public synchronized Enumeration keys() 126 { 127 return new LruHashtableEnumerator( oldTable, newTable, true ); 128 } 129 130 public synchronized Enumeration elements() 135 { 136 return new LruHashtableEnumerator( oldTable, newTable, false ); 137 } 138 139 public synchronized boolean contains( Object value ) 146 { 147 if ( newTable.contains( value ) ) 148 return true; 149 if ( oldTable.contains( value ) ) 150 { 151 return true; 158 } 159 return false; 160 } 161 162 public synchronized boolean containsKey( Object key ) 166 { 167 if ( newTable.containsKey( key ) ) 168 return true; 169 if ( oldTable.containsKey( key ) ) 170 { 171 Object value = oldTable.get( key ); 173 newTable.put( key, value ); 174 oldTable.remove( key ); 175 return true; 176 } 177 return false; 178 } 179 180 public synchronized Object get( Object key ) 187 { 188 Object value; 189 value = newTable.get( key ); 190 if ( value != null ) 191 return value; 192 value = oldTable.get( key ); 193 if ( value != null ) 194 { 195 newTable.put( key, value ); 197 oldTable.remove( key ); 198 return value; 199 } 200 return null; 201 } 202 203 public synchronized Object put( Object key, Object value ) 213 { 214 Object oldValue = newTable.put( key, value ); 215 if ( oldValue != null ) 216 return oldValue; 217 oldValue = oldTable.get( key ); 218 if ( oldValue != null ) 219 oldTable.remove( key ); 220 else 221 { 222 if ( size() >= threshold ) 223 { 224 oldTable = newTable; 226 newTable = new Hashtable ( eachCapacity, loadFactor ); 227 } 228 } 229 return oldValue; 230 } 231 232 public synchronized Object remove( Object key ) 237 { 238 Object oldValue = newTable.remove( key ); 239 if ( oldValue == null ) 240 oldValue = oldTable.remove( key ); 241 return oldValue; 242 } 243 244 public synchronized void clear() 246 { 247 newTable.clear(); 248 oldTable.clear(); 249 } 250 251 public synchronized Object clone() 255 { 256 LruHashtable n = (LruHashtable) super.clone(); 257 n.newTable = (Hashtable ) n.newTable.clone(); 258 n.oldTable = (Hashtable ) n.oldTable.clone(); 259 return n; 260 } 261 262 264 } 265 266 267 class LruHashtableEnumerator implements Enumeration 268 { 269 Enumeration oldEnum; 270 Enumeration newEnum; 271 boolean old; 272 273 LruHashtableEnumerator( Hashtable oldTable, Hashtable newTable, boolean keys ) 274 { 275 if ( keys ) 276 { 277 oldEnum = oldTable.keys(); 278 newEnum = newTable.keys(); 279 } 280 else 281 { 282 oldEnum = oldTable.elements(); 283 newEnum = newTable.elements(); 284 } 285 old = true; 286 } 287 288 public boolean hasMoreElements() 289 { 290 boolean r; 291 if ( old ) 292 { 293 r = oldEnum.hasMoreElements(); 294 if ( ! r ) 295 { 296 old = false; 297 r = newEnum.hasMoreElements(); 298 } 299 } 300 else 301 r = newEnum.hasMoreElements(); 302 return r; 303 } 304 305 public Object nextElement() 306 { 307 if ( old ) 308 return oldEnum.nextElement(); 309 return newEnum.nextElement(); 310 } 311 312 } 313 314 | Popular Tags |