1 28 29 package com.caucho.util; 30 31 import java.util.Iterator ; 32 33 38 public class LongKeyHashMap<E> { 39 private long []_keys; 41 42 private E []_values; 44 45 private int _size; 47 private int _mask; 48 49 54 public LongKeyHashMap(int initialCapacity) 55 { 56 int capacity; 57 58 for (capacity = 8; capacity < 2 * initialCapacity; capacity *= 2) { 59 } 60 61 _keys = new long[capacity]; 62 _values = (E []) new Object [capacity]; 63 _mask = capacity - 1; 64 } 65 66 69 public int size() 70 { 71 return _size; 72 } 73 74 77 public void clear() 78 { 79 synchronized (this) { 80 for (int i = 0; i < _values.length; i++) { 81 _values[i] = null; 82 } 83 84 _size = 0; 85 } 86 } 87 88 94 public E get(long key) 95 { 96 int hash = getHash(key); 97 int count = _size + 1; 98 99 synchronized (this) { 100 for (; count > 0; count--) { 101 E item = _values[hash]; 102 103 if (item == null) 104 return null; 105 106 if (_keys[hash] == key) 107 return item; 108 109 hash = (hash + 1) & _mask; 110 } 111 } 112 113 return null; 114 } 115 116 125 public E put(long key, E value) 126 { 127 E item = putImpl(key, value); 128 129 if (_values.length <= 2 * _size) { 131 synchronized (this) { 132 long []oldKeys = _keys; 133 E []oldValues = _values; 134 135 _keys = new long[2 * oldKeys.length]; 136 _values = (E []) new Object [2 * oldValues.length]; 137 138 _mask = _values.length - 1; 139 140 for (int i = oldValues.length - 1; i >= 0; i--) { 141 long oldKey = oldKeys[i]; 142 E oldValue = oldValues[i]; 143 144 if (oldValue != null) 145 putImpl(oldKey, oldValue); 146 } 147 } 148 } 149 150 return item; 151 } 152 153 156 private E putImpl(long key, E value) 157 { 158 E item = null; 159 160 int hash = getHash(key); 161 int count = _size + 1; 162 163 synchronized (this) { 164 for (; count > 0; count--) { 165 item = _values[hash]; 166 167 if (item == null) { 169 _keys[hash] = key; 170 _values[hash] = value; 171 _size++; 172 173 return null; 174 } 175 176 if (_keys[hash] == key) { 178 _values[hash] = value; 179 180 return item; 181 } 182 183 hash = (hash + 1) & _mask; 184 } 185 } 186 187 throw new IllegalStateException (); 188 } 189 190 197 public E remove(long key) 198 { 199 int hash = getHash(key); 200 int count = _size + 1; 201 202 E item = null; 203 204 synchronized (this) { 205 for (; count > 0; count--) { 206 item = _values[hash]; 207 208 if (item == null) 209 return null; 210 211 if (_keys[hash] == key) { 212 _values[hash] = null; 213 _size--; 214 215 refillEntries(hash); 216 break; 217 } 218 219 hash = (hash + 1) & _mask; 220 } 221 } 222 223 if (count < 0) 224 throw new RuntimeException ("internal cache error"); 225 226 return item; 227 } 228 229 232 private void refillEntries(int hash) 233 { 234 for (int count = _size; count >= 0; count--) { 235 hash = (hash + 1) & _mask; 236 237 if (_values[hash] == null) 238 return; 239 240 _values[hash] = null; 241 refillEntry(hash); 242 } 243 } 244 245 248 private void refillEntry(int baseHash) 249 { 250 long key = _keys[baseHash]; 251 E value = _values[baseHash]; 252 253 int hash = getHash(key); 254 255 for (int count = _size; count >= 0; count--) { 256 if (_values[hash] == null) { 257 _keys[hash] = key; 258 _values[hash] = value; 259 return; 260 } 261 262 hash = (hash + 1) & _mask; 263 } 264 } 265 266 269 private int getHash(long key) 270 { 271 long hash = key; 272 hash = hash * 0x5deece66dl + 0xbl + (hash >>> 32) * 137; 273 274 return (int) (hash) & _mask; 275 } 276 277 public Iterator <E> valueIterator() 278 { 279 return new ValueIterator(); 280 } 281 282 class ValueIterator implements Iterator <E> { 283 private E []_values; 284 private int _index; 285 private E _value; 286 287 ValueIterator() 288 { 289 _values = LongKeyHashMap.this._values; 290 _index = -1; 291 findNext(); 292 } 293 294 public boolean hasNext() 295 { 296 return _value != null; 297 } 298 299 public E next() 300 { 301 E value = _value; 302 findNext(); 303 return value; 304 } 305 306 public void remove() 307 { 308 } 309 310 private void findNext() 311 { 312 _value = null; 313 314 for (_index++; _index < _values.length; _index++) { 315 _value = _values[_index]; 316 if (_value != null) 317 return; 318 } 319 } 320 } 321 } 322 | Popular Tags |