1 21 package oracle.toplink.essentials.internal.helper; 23 24 25 42 43 import java.io.*; 45 import java.util.*; 46 47 public class TopLinkIdentityHashSet extends AbstractCollection implements Set, Cloneable , Serializable { 48 static final long serialVersionUID = 1619330892277906704L; 49 50 static final int DEFAULT_INITIAL_CAPACITY = 32; 52 53 static final int MAXIMUM_CAPACITY = 1 << 30; 55 56 static final float DEFAULT_LOAD_FACTOR = 0.75f; 58 protected transient Entry[] entries; protected transient int count = 0; 60 protected int threshold = 0; 61 protected float loadFactor = 0; 62 63 73 public TopLinkIdentityHashSet(int initialCapacity, float loadFactor) { 74 if (initialCapacity < 0) { 75 throw new IllegalArgumentException ("Illegal initialCapacity: " + initialCapacity); 76 } 77 if (initialCapacity > MAXIMUM_CAPACITY) { 78 initialCapacity = MAXIMUM_CAPACITY; 79 } 80 if ((loadFactor <= 0) || Float.isNaN(loadFactor)) { 81 throw new IllegalArgumentException ("Illegal loadFactor: " + loadFactor); 82 } 83 84 int capacity = 1; 86 while (capacity < initialCapacity) { 87 capacity <<= 1; 88 } 89 this.loadFactor = loadFactor; 90 threshold = (int)(capacity * loadFactor); 91 entries = new Entry[capacity]; 92 } 93 94 102 public TopLinkIdentityHashSet(int initialCapacity) { 103 this(initialCapacity, DEFAULT_LOAD_FACTOR); 104 } 105 106 110 public TopLinkIdentityHashSet() { 111 loadFactor = DEFAULT_LOAD_FACTOR; 112 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); 113 entries = new Entry[DEFAULT_INITIAL_CAPACITY]; 114 } 115 116 125 public TopLinkIdentityHashSet(Collection c) { 126 this(Math.max((int)(c.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); 127 addAll(c); 128 } 129 130 133 public int size() { 134 return count; 135 } 136 137 140 public boolean isEmpty() { 141 return (count == 0); 142 } 143 144 152 public boolean contains(Object obj) { 153 if (obj == null) { 154 return false; 155 } 156 157 Entry[] copyOfEntries = entries; 158 int hash = System.identityHashCode(obj); 159 int index = (hash & 0x7FFFFFFF) % copyOfEntries.length; 160 for (Entry e = copyOfEntries[index]; e != null; e = e.next) { 161 if ((e.hash == hash) && (obj == e.value)) { 162 return true; 163 } 164 } 165 return false; 166 } 167 168 174 private void rehash() { 175 int oldCapacity = entries.length; 176 Entry[] oldEntries = entries; 177 int newCapacity = (oldCapacity * 2) + 1; 178 Entry[] newEntries = new Entry[newCapacity]; 179 threshold = (int)(newCapacity * loadFactor); 180 entries = newEntries; 181 for (int i = oldCapacity; i-- > 0;) { 182 for (Entry old = oldEntries[i]; old != null;) { 183 Entry e = old; 184 old = old.next; 185 int index = (e.hash & 0x7FFFFFFF) % newCapacity; 186 e.next = newEntries[index]; 187 newEntries[index] = e; 188 } 189 } 190 } 191 192 200 public boolean add(Object obj) { 201 if (obj == null) { 202 throw new NullPointerException (); 203 } 204 205 Entry[] copyOfEntries = entries; 207 int hash = System.identityHashCode(obj); 208 int index = (hash & 0x7FFFFFFF) % copyOfEntries.length; 209 for (Entry e = copyOfEntries[index]; e != null; e = e.next) { 210 if ((e.hash == hash) && (obj == e.value)) { 211 return false; 212 } 213 } 214 215 if (count >= threshold) { 216 rehash(); 218 copyOfEntries = entries; 219 index = (hash & 0x7FFFFFFF) % copyOfEntries.length; 220 } 221 222 Entry e = new Entry(hash, obj, copyOfEntries[index]); 224 copyOfEntries[index] = e; 225 count++; 226 return true; 227 } 228 229 237 public boolean remove(Object obj) { 238 if (obj == null) { 239 return false; 240 } 241 242 Entry[] copyOfEntries = entries; 243 int hash = System.identityHashCode(obj); 244 int index = (hash & 0x7FFFFFFF) % copyOfEntries.length; 245 for (Entry e = copyOfEntries[index], prev = null; e != null; prev = e, e = e.next) { 246 if ((e.hash == hash) && (obj == e.value)) { 247 if (prev != null) { 248 prev.next = e.next; 249 } else { 250 copyOfEntries[index] = e.next; 251 } 252 count--; 253 return true; 254 } 255 } 256 return false; 257 } 258 259 264 public boolean removeAll(Collection c) { 265 throw new UnsupportedOperationException ("TopLinkIdentityHashSet removeAll"); 266 } 267 268 273 public boolean retainAll(Collection c) { 274 throw new UnsupportedOperationException ("TopLinkIdentityHashSet retainAll"); 275 } 276 277 280 public void clear() { 281 if (count > 0) { 282 Entry[] copyOfEntries = entries; 283 for (int i = copyOfEntries.length; --i >= 0;) { 284 copyOfEntries[i] = null; 285 } 286 count = 0; 287 } 288 } 289 290 296 public Object clone() { 297 try { 298 Entry[] copyOfEntries = entries; 299 TopLinkIdentityHashSet clone = (TopLinkIdentityHashSet)super.clone(); 300 clone.entries = new Entry[copyOfEntries.length]; 301 for (int i = copyOfEntries.length; i-- > 0;) { 302 clone.entries[i] = (copyOfEntries[i] != null) ? (Entry)copyOfEntries[i].clone() : null; 303 } 304 return clone; 305 } catch (CloneNotSupportedException e) { 306 throw new InternalError (); 308 } 309 } 310 311 314 public Iterator iterator() { 315 return new TopLinkIdentityHashSetIterator(); 316 } 317 318 321 static class Entry { 322 int hash; 323 Object value; 324 Entry next; 325 326 Entry(int hash, Object value, Entry next) { 327 this.hash = hash; 328 this.value = value; 329 this.next = next; 330 } 331 332 protected Object clone() { 333 return new Entry(hash, value, ((next == null) ? null : (Entry)next.clone())); 334 } 335 } 336 337 class TopLinkIdentityHashSetIterator implements Iterator { 338 Entry[] copyOfEntries = TopLinkIdentityHashSet.this.entries; 339 int index = copyOfEntries.length; 340 Entry entry = null; 341 Entry lastReturned = null; 342 343 TopLinkIdentityHashSetIterator() { 344 } 345 346 public boolean hasNext() { 347 Entry e = entry; 348 int i = index; 349 Entry[] tmp = copyOfEntries; 350 while ((e == null) && (i > 0)) { 351 e = tmp[--i]; 352 } 353 entry = e; 354 index = i; 355 return e != null; 356 } 357 358 public Object next() { 359 Entry et = entry; 360 int i = index; 361 Entry[] tmp = copyOfEntries; 362 363 while ((et == null) && (i > 0)) { 364 et = tmp[--i]; 365 } 366 entry = et; 367 index = i; 368 if (et != null) { 369 Entry e = lastReturned = entry; 370 entry = e.next; 371 return e.value; 372 } 373 throw new NoSuchElementException(); 374 } 375 376 public void remove() { 377 if (lastReturned == null) { 378 throw new IllegalStateException (); 379 } 380 381 Entry[] copyOfEntries = TopLinkIdentityHashSet.this.entries; 382 int index = (lastReturned.hash & 0x7FFFFFFF) % copyOfEntries.length; 383 for (Entry e = copyOfEntries[index], prev = null; e != null; prev = e, e = e.next) { 384 if (e == lastReturned) { 385 if (prev == null) { 386 copyOfEntries[index] = e.next; 387 } else { 388 prev.next = e.next; 389 } 390 count--; 391 lastReturned = null; 392 return; 393 } 394 } 395 throw new ConcurrentModificationException(); 396 } 397 } 398 399 407 private void writeObject(ObjectOutputStream s) throws IOException, ClassNotFoundException { 408 s.defaultWriteObject(); 410 411 s.writeInt(entries.length); 413 s.writeInt(count); 415 for (Iterator i = iterator(); i.hasNext();) { 417 s.writeObject(i.next()); 418 } 419 } 420 421 424 private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { 425 s.defaultReadObject(); 427 428 int numBuckets = s.readInt(); 430 entries = new Entry[numBuckets]; 431 int size = s.readInt(); 433 434 for (int i = 0; i < size; i++) { 436 add(s.readObject()); 437 } 438 } 439 } 440 | Popular Tags |