1 21 package oracle.toplink.essentials.internal.helper; 23 24 25 34 35 import java.io.*; 37 import java.util.*; 38 39 public class IdentityHashtable extends Dictionary implements Cloneable , Serializable { 40 static final long serialVersionUID = 1421746759512286392L; 41 42 static final int DEFAULT_INITIAL_CAPACITY = 32; 44 45 static final int MAXIMUM_CAPACITY = 1 << 30; 47 48 static final float DEFAULT_LOAD_FACTOR = 0.75f; 50 51 52 static final int KEYS = 0; 53 54 55 static final int ELEMENTS = 1; 56 private static EmptyEnumerator emptyEnumerator = new EmptyEnumerator(); 57 protected transient Entry[] entries; protected transient int count = 0; 59 protected int threshold = 0; 60 protected float loadFactor = 0; 61 62 72 public IdentityHashtable(int initialCapacity, float loadFactor) { 73 if (initialCapacity < 0) { 74 throw new IllegalArgumentException ("Illegal initialCapacity: " + initialCapacity); 75 } 76 if (initialCapacity > MAXIMUM_CAPACITY) { 77 initialCapacity = MAXIMUM_CAPACITY; 78 } 79 if ((loadFactor <= 0) || Float.isNaN(loadFactor)) { 80 throw new IllegalArgumentException ("Illegal loadFactor: " + loadFactor); 81 } 82 83 int capacity = 1; 85 while (capacity < initialCapacity) { 86 capacity <<= 1; 87 } 88 this.loadFactor = loadFactor; 89 threshold = (int)(capacity * loadFactor); 90 entries = new Entry[capacity]; 91 } 92 93 102 public IdentityHashtable(int initialCapacity) { 103 this(initialCapacity, DEFAULT_LOAD_FACTOR); 104 } 105 106 110 public IdentityHashtable() { 111 loadFactor = DEFAULT_LOAD_FACTOR; 112 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); 113 entries = new Entry[DEFAULT_INITIAL_CAPACITY]; 114 } 115 116 119 public synchronized void clear() { 120 if (count > 0) { 121 Entry[] copyOfEntries = entries; 122 for (int i = copyOfEntries.length; --i >= 0;) { 123 copyOfEntries[i] = null; 124 } 125 count = 0; 126 } 127 } 128 129 135 public synchronized Object clone() { 136 try { 137 Entry[] copyOfEntries = entries; 138 IdentityHashtable clone = (IdentityHashtable)super.clone(); 139 clone.entries = new Entry[copyOfEntries.length]; 140 for (int i = copyOfEntries.length; i-- > 0;) { 141 clone.entries[i] = (copyOfEntries[i] != null) ? (Entry)copyOfEntries[i].clone() : null; 142 } 143 return clone; 144 } catch (CloneNotSupportedException e) { 145 throw new InternalError (); 147 } 148 } 149 150 159 public synchronized boolean contains(Object obj) { 160 if (obj == null) { 161 throw new NullPointerException (); 162 } 163 164 Entry[] copyOfEntries = entries; 165 for (int i = copyOfEntries.length; i-- > 0;) { 166 for (Entry e = copyOfEntries[i]; e != null; e = e.next) { 167 if (e.value.equals(obj)) { 168 return true; 169 } 170 } 171 } 172 return false; 173 } 174 175 184 public synchronized boolean containsKey(Object key) { 185 Entry[] copyOfEntries = entries; 186 int hash = System.identityHashCode(key); 187 int index = (hash & 0x7FFFFFFF) % copyOfEntries.length; 188 for (Entry e = copyOfEntries[index]; e != null; e = e.next) { 189 if (e.key == key) { 190 return true; 191 } 192 } 193 return false; 194 } 195 196 public synchronized Enumeration elements() { 197 if (count == 0) { 198 return emptyEnumerator; 199 } else { 200 return new Enumerator(ELEMENTS); 201 } 202 } 203 204 213 public synchronized Object get(Object key) { 214 Entry[] copyOfEntries = entries; 215 int hash = System.identityHashCode(key); 216 int index = (hash & 0x7FFFFFFF) % copyOfEntries.length; 217 for (Entry e = copyOfEntries[index]; e != null; e = e.next) { 218 if (e.key == key) { 219 return e.value; 220 } 221 } 222 return null; 223 } 224 225 228 public boolean isEmpty() { 229 return (count == 0); 230 } 231 232 public synchronized Enumeration keys() { 233 if (count == 0) { 234 return emptyEnumerator; 235 } else { 236 return new Enumerator(KEYS); 237 } 238 } 239 240 250 public synchronized Object put(Object key, Object obj) { 251 if (obj == null) { 252 throw new NullPointerException (); 253 } 254 255 Entry[] copyOfEntries = entries; 256 int hash = System.identityHashCode(key); 257 int index = (hash & 0x7FFFFFFF) % copyOfEntries.length; 258 for (Entry e = copyOfEntries[index]; e != null; e = e.next) { 259 if (e.key == key) { 260 Object old = e.value; 261 e.value = obj; 262 return old; 263 } 264 } 265 266 if (count >= threshold) { 267 rehash(); 268 copyOfEntries = entries; 269 index = (hash & 0x7FFFFFFF) % copyOfEntries.length; 270 } 271 Entry e = new Entry(hash, key, obj, copyOfEntries[index]); 272 copyOfEntries[index] = e; 273 count++; 274 return null; 275 } 276 277 283 private void rehash() { 284 int oldCapacity = entries.length; 285 Entry[] oldEntries = entries; 286 int newCapacity = (oldCapacity * 2) + 1; 287 Entry[] newEntries = new Entry[newCapacity]; 288 threshold = (int)(newCapacity * loadFactor); 289 entries = newEntries; 290 for (int i = oldCapacity; i-- > 0;) { 291 for (Entry old = oldEntries[i]; old != null;) { 292 Entry e = old; 293 old = old.next; 294 int index = (e.hash & 0x7FFFFFFF) % newCapacity; 295 e.next = newEntries[index]; 296 newEntries[index] = e; 297 } 298 } 299 } 300 301 309 public synchronized Object remove(Object key) { 310 Entry[] copyOfEntries = entries; 311 int hash = System.identityHashCode(key); 312 int index = (hash & 0x7FFFFFFF) % copyOfEntries.length; 313 for (Entry e = copyOfEntries[index], prev = null; e != null; prev = e, e = e.next) { 314 if (e.key == key) { 315 if (prev != null) { 316 prev.next = e.next; 317 } else { 318 copyOfEntries[index] = e.next; 319 } 320 count--; 321 return e.value; 322 } 323 } 324 return null; 325 } 326 327 330 public int size() { 331 return count; 332 } 333 334 339 public synchronized String toString() { 340 int max = size() - 1; 341 StringBuffer buf = new StringBuffer (); 342 Enumeration k = keys(); 343 Enumeration e = elements(); 344 buf.append("{"); 345 for (int i = 0; i <= max; i++) { 346 String s1 = k.nextElement().toString(); 347 String s2 = e.nextElement().toString(); 348 buf.append(s1 + "=" + s2); 349 if (i < max) { 350 buf.append(", "); 351 } 352 } 353 buf.append("}"); 354 return buf.toString(); 355 } 356 357 365 private void writeObject(ObjectOutputStream s) throws IOException { 366 s.defaultWriteObject(); 368 369 s.writeInt(entries.length); 371 s.writeInt(count); 373 for (int i = entries.length - 1; i >= 0; i--) { 375 Entry entry = entries[i]; 376 while (entry != null) { 377 s.writeObject(entry.key); 378 s.writeObject(entry.value); 379 entry = entry.next; 380 } 381 } 382 } 383 384 387 private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { 388 s.defaultReadObject(); 390 391 int numBuckets = s.readInt(); 393 entries = new Entry[numBuckets]; 394 int size = s.readInt(); 396 397 for (int i = 0; i < size; i++) { 399 Object key = s.readObject(); 400 Object value = s.readObject(); 401 put(key, value); 402 } 403 } 404 405 private static class EmptyEnumerator implements Enumeration { 406 EmptyEnumerator() { 407 } 408 409 public boolean hasMoreElements() { 410 return false; 411 } 412 413 public Object nextElement() { 414 throw new NoSuchElementException(); 415 } 416 } 417 418 class Enumerator implements Enumeration { 419 int enumeratorType; 420 int index; 421 Entry entry; 422 423 Enumerator(int enumeratorType) { 424 this.enumeratorType = enumeratorType; 425 index = IdentityHashtable.this.entries.length; 426 } 427 428 public boolean hasMoreElements() { 429 if (entry != null) { 430 return true; 431 } 432 while (index-- > 0) { 433 if ((entry = IdentityHashtable.this.entries[index]) != null) { 434 return true; 435 } 436 } 437 return false; 438 } 439 440 public Object nextElement() { 441 if (entry == null) { 442 while ((index-- > 0) && ((entry = IdentityHashtable.this.entries[index]) == null)) { 443 ; 444 } 445 } 446 if (entry != null) { 447 Entry e = entry; 448 entry = e.next; 449 if (enumeratorType == KEYS) { 450 return e.key; 451 } else { 452 return e.value; 453 } 454 } 455 throw new NoSuchElementException("IdentityHashtable.Enumerator"); 456 } 457 } 458 459 462 private static class Entry { 463 int hash; 464 Object key; 465 Object value; 466 Entry next; 467 468 Entry(int hash, Object key, Object value, Entry next) { 469 this.hash = hash; 470 this.key = key; 471 this.value = value; 472 this.next = next; 473 } 474 475 protected Object clone() { 476 return new Entry(hash, key, value, ((next == null) ? null : (Entry)next.clone())); 477 } 478 479 public Object getKey() { 480 return key; 481 } 482 483 public Object getValue() { 484 return value; 485 } 486 487 public Object setValue(Object value) { 488 Object oldValue = this.value; 489 this.value = value; 490 return oldValue; 491 } 492 493 public boolean equals(Object o) { 494 if (!(o instanceof Entry)) { 495 return false; 496 } 497 498 Entry e = (Entry)o; 499 return (key == e.getKey()) && ((value == null) ? (e.getValue() == null) : value.equals(e.getValue())); 500 } 501 502 public int hashCode() { 503 return hash ^ ((value == null) ? 0 : value.hashCode()); 504 } 505 506 public String toString() { 507 return key + "=" + value; 508 } 509 } 510 } 511 | Popular Tags |