00001 package edu.ksu.cis.bandera.abstraction.util;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import java.util.*;
00036 import java.io.*;
00037 public class RefHashTable extends Dictionary implements Map, Cloneable, java.io.Serializable {
00038
00039
00040
00041 private transient Entry table[];
00042
00043
00044
00045
00046 private transient int count;
00047
00048
00049
00050
00051
00052
00053
00054 private int threshold;
00055
00056
00057
00058
00059
00060
00061 private float loadFactor;
00062
00063
00064
00065
00066
00067
00068
00069
00070 private transient int modCount = 0;
00071
00072
00073
00074 private transient Set keySet = null;
00075 private transient Set entrySet = null;
00076 private transient Collection values = null;
00077 private class KeySet extends AbstractSet {
00078 public Iterator iterator() {
00079 return new Enumerator(KEYS, true);
00080 }
00081 public int size() {
00082 return count;
00083 }
00084 public boolean contains(Object o) {
00085 return containsKey(o);
00086 }
00087 public boolean remove(Object o) {
00088 return RefHashTable.this.remove(o) != null;
00089 }
00090 public void clear() {
00091 RefHashTable.this.clear();
00092 }
00093 }
00094 private class EntrySet extends AbstractSet {
00095 public Iterator iterator() {
00096 return new Enumerator(ENTRIES, true);
00097 }
00098 public boolean contains(Object o) {
00099 if (!(o instanceof Map.Entry))
00100 return false;
00101 Map.Entry entry = (Map.Entry) o;
00102 Object key = entry.getKey();
00103 Entry tab[] = table;
00104 int hash = key.hashCode();
00105 int index = (hash & 0x7FFFFFFF) % tab.length;
00106 for (Entry e = tab[index]; e != null; e = e.next)
00107 if (e.hash == hash && e.equals(entry))
00108 return true;
00109 return false;
00110 }
00111 public boolean remove(Object o) {
00112 if (!(o instanceof Map.Entry))
00113 return false;
00114 Map.Entry entry = (Map.Entry) o;
00115 Object key = entry.getKey();
00116 Entry tab[] = table;
00117 int hash = key.hashCode();
00118 int index = (hash & 0x7FFFFFFF) % tab.length;
00119 for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) {
00120 if (e.hash == hash && e.equals(entry)) {
00121 modCount++;
00122 if (prev != null)
00123 prev.next = e.next;
00124 else
00125 tab[index] = e.next;
00126 count--;
00127 e.value = null;
00128 return true;
00129 }
00130 }
00131 return false;
00132 }
00133 public int size() {
00134 return count;
00135 }
00136 public void clear() {
00137 RefHashTable.this.clear();
00138 }
00139 }
00140 private class ValueCollection extends AbstractCollection {
00141 public Iterator iterator() {
00142 return new Enumerator(VALUES, true);
00143 }
00144 public int size() {
00145 return count;
00146 }
00147 public boolean contains(Object o) {
00148 return containsValue(o);
00149 }
00150 public void clear() {
00151 RefHashTable.this.clear();
00152 }
00153 }
00154
00155
00156
00157
00158 private static class Entry implements Map.Entry {
00159 int hash;
00160 Object key;
00161 Object value;
00162 Entry next;
00163 protected Entry(int hash, Object key, Object value, Entry next) {
00164 this.hash = hash;
00165 this.key = key;
00166 this.value = value;
00167 this.next = next;
00168 }
00169 protected Object clone() {
00170 return new Entry(hash, key, value, (next == null ? null : (Entry) next.clone()));
00171 }
00172
00173
00174
00175 public Object getKey() {
00176 return key;
00177 }
00178 public Object getValue() {
00179 return value;
00180 }
00181 public Object setValue(Object value) {
00182 if (value == null)
00183 throw new NullPointerException();
00184 Object oldValue = this.value;
00185 this.value = value;
00186 return oldValue;
00187 }
00188 public boolean equals(Object o) {
00189 if (!(o instanceof Map.Entry))
00190 return false;
00191 Map.Entry e = (Map.Entry) o;
00192 return (key == null ? e.getKey() == null : key == e.getKey()) && (value == null ? e.getValue() == null : value.equals(e.getValue()));
00193 }
00194 public int hashCode() {
00195 return hash ^ (value == null ? 0 : value.hashCode());
00196 }
00197 public String toString() {
00198 return key.toString() + "=" + value.toString();
00199 }
00200 }
00201
00202
00203 private static final int KEYS = 0;
00204 private static final int VALUES = 1;
00205 private static final int ENTRIES = 2;
00206
00207
00208
00209
00210
00211
00212
00213
00214 private class Enumerator implements Enumeration, Iterator {
00215 Entry[] table = RefHashTable.this.table;
00216 int index = table.length;
00217 Entry entry = null;
00218 Entry lastReturned = null;
00219 int type;
00220
00221
00222
00223
00224
00225 boolean iterator;
00226
00227
00228
00229
00230
00231
00232 private int expectedModCount = modCount;
00233 Enumerator(int type, boolean iterator) {
00234 this.type = type;
00235 this.iterator = iterator;
00236 }
00237 public boolean hasMoreElements() {
00238 while (entry == null && index > 0)
00239 entry = table[--index];
00240 return entry != null;
00241 }
00242 public Object nextElement() {
00243 while (entry == null && index > 0)
00244 entry = table[--index];
00245 if (entry != null) {
00246 Entry e = lastReturned = entry;
00247 entry = e.next;
00248 return type == KEYS ? e.key : (type == VALUES ? e.value : e);
00249 }
00250 throw new NoSuchElementException("RefHashTable Enumerator");
00251 }
00252
00253
00254 public boolean hasNext() {
00255 return hasMoreElements();
00256 }
00257 public Object next() {
00258 if (modCount != expectedModCount)
00259 throw new ConcurrentModificationException();
00260 return nextElement();
00261 }
00262 public void remove() {
00263 if (!iterator)
00264 throw new UnsupportedOperationException();
00265 if (lastReturned == null)
00266 throw new IllegalStateException("RefHashTable Enumerator");
00267 if (modCount != expectedModCount)
00268 throw new ConcurrentModificationException();
00269 synchronized (RefHashTable.this) {
00270 Entry[] tab = RefHashTable.this.table;
00271 int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length;
00272 for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) {
00273 if (e == lastReturned) {
00274 modCount++;
00275 expectedModCount++;
00276 if (prev == null)
00277 tab[index] = e.next;
00278 else
00279 prev.next = e.next;
00280 count--;
00281 lastReturned = null;
00282 return;
00283 }
00284 }
00285 throw new ConcurrentModificationException();
00286 }
00287 }
00288 }
00289
00290
00291
00292
00293 public RefHashTable() {
00294 this(101, 0.75f);
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304 public RefHashTable(int initialCapacity) {
00305 this(initialCapacity, 0.75f);
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 public RefHashTable(int initialCapacity, float loadFactor) {
00317 if (initialCapacity < 0)
00318 throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
00319 if (loadFactor <= 0)
00320 throw new IllegalArgumentException("Illegal Load: " + loadFactor);
00321 if (initialCapacity == 0)
00322 initialCapacity = 1;
00323 this.loadFactor = loadFactor;
00324 table = new Entry[initialCapacity];
00325 threshold = (int) (initialCapacity * loadFactor);
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335 public RefHashTable(Map t) {
00336 this(Math.max(2 * t.size(), 11), 0.75f);
00337 putAll(t);
00338 }
00339
00340
00341
00342 public synchronized void clear() {
00343 Entry tab[] = table;
00344 modCount++;
00345 for (int index = tab.length; --index >= 0;)
00346 tab[index] = null;
00347 count = 0;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356 public synchronized Object clone() {
00357 try {
00358 RefHashTable t = (RefHashTable) super.clone();
00359 t.table = new Entry[table.length];
00360 for (int i = table.length; i-- > 0;) {
00361 t.table[i] = (table[i] != null) ? (Entry) table[i].clone() : null;
00362 }
00363 t.keySet = null;
00364 t.entrySet = null;
00365 t.values = null;
00366 t.modCount = 0;
00367 return t;
00368 } catch (CloneNotSupportedException e) {
00369
00370 throw new InternalError();
00371 }
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 public synchronized boolean contains(Object value) {
00392 if (value == null) {
00393 throw new NullPointerException();
00394 }
00395 Entry tab[] = table;
00396 for (int i = tab.length; i-- > 0;) {
00397 for (Entry e = tab[i]; e != null; e = e.next) {
00398 if (e.value.equals(value)) {
00399 return true;
00400 }
00401 }
00402 }
00403 return false;
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 public synchronized boolean containsKey(Object key) {
00415 Entry tab[] = table;
00416 int hash = key.hashCode();
00417 int index = (hash & 0x7FFFFFFF) % tab.length;
00418 for (Entry e = tab[index]; e != null; e = e.next) {
00419 if ((e.hash == hash) && e.key == key) {
00420 return true;
00421 }
00422 }
00423 return false;
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 public boolean containsValue(Object value) {
00436 return contains(value);
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 public synchronized Enumeration elements() {
00450 return new Enumerator(VALUES, false);
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 public Set entrySet() {
00464 if (entrySet == null)
00465 entrySet = Collections.synchronizedSet(new EntrySet());
00466 return entrySet;
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 public synchronized boolean equals(Object o) {
00479 if (o == this)
00480 return true;
00481 if (!(o instanceof Map))
00482 return false;
00483 Map t = (Map) o;
00484 if (t.size() != size())
00485 return false;
00486 Iterator i = entrySet().iterator();
00487 while (i.hasNext()) {
00488 Entry e = (Entry) i.next();
00489 Object key = e.getKey();
00490 Object value = e.getValue();
00491 if (value == null) {
00492 if (!(t.get(key) == null && t.containsKey(key)))
00493 return false;
00494 } else {
00495 if (!value.equals(t.get(key)))
00496 return false;
00497 }
00498 }
00499 return true;
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 public synchronized Object get(Object key) {
00511 Entry tab[] = table;
00512 int hash = key.hashCode();
00513 int index = (hash & 0x7FFFFFFF) % tab.length;
00514 for (Entry e = tab[index]; e != null; e = e.next) {
00515 if ((e.hash == hash) && e.key == key) {
00516 return e.value;
00517 }
00518 }
00519 return null;
00520 }
00521
00522
00523
00524
00525
00526
00527
00528 public synchronized int hashCode() {
00529 int h = 0;
00530 Iterator i = entrySet().iterator();
00531 while (i.hasNext())
00532 h += i.next().hashCode();
00533 return h;
00534 }
00535
00536
00537
00538
00539
00540
00541 public boolean isEmpty() {
00542 return count == 0;
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553 public synchronized Enumeration keys() {
00554 return new Enumerator(KEYS, false);
00555 }
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 public Set keySet() {
00566 if (keySet == null)
00567 keySet = Collections.synchronizedSet(new KeySet());
00568 return keySet;
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 public synchronized Object put(Object key, Object value) {
00588
00589 if (value == null) {
00590 throw new NullPointerException();
00591 }
00592
00593
00594 Entry tab[] = table;
00595 int hash = key.hashCode();
00596 int index = (hash & 0x7FFFFFFF) % tab.length;
00597 for (Entry e = tab[index]; e != null; e = e.next) {
00598 if ((e.hash == hash) && e.key == key) {
00599 Object old = e.value;
00600 e.value = value;
00601 return old;
00602 }
00603 }
00604 modCount++;
00605 if (count >= threshold) {
00606
00607 rehash();
00608 tab = table;
00609 index = (hash & 0x7FFFFFFF) % tab.length;
00610 }
00611
00612
00613 Entry e = new Entry(hash, key, value, tab[index]);
00614 tab[index] = e;
00615 count++;
00616 return null;
00617 }
00618
00619
00620
00621
00622
00623
00624
00625 public synchronized void putAll(Map t) {
00626 Iterator i = t.entrySet().iterator();
00627 while (i.hasNext()) {
00628 Map.Entry e = (Map.Entry) i.next();
00629 put(e.getKey(), e.getValue());
00630 }
00631 }
00632
00633
00634
00635 private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
00636
00637 s.defaultReadObject();
00638
00639
00640 int origlength = s.readInt();
00641 int elements = s.readInt();
00642
00643
00644
00645
00646
00647 int length = (int) (elements * loadFactor) + (elements / 20) + 3;
00648 if (length > elements && (length & 1) == 0)
00649 length--;
00650 if (origlength > 0 && length > origlength)
00651 length = origlength;
00652 table = new Entry[length];
00653 count = 0;
00654
00655
00656 for (; elements > 0; elements--) {
00657 Object key = s.readObject();
00658 Object value = s.readObject();
00659 put(key, value);
00660 }
00661 }
00662
00663
00664
00665
00666
00667
00668
00669 protected void rehash() {
00670 int oldCapacity = table.length;
00671 Entry oldMap[] = table;
00672 int newCapacity = oldCapacity * 2 + 1;
00673 Entry newMap[] = new Entry[newCapacity];
00674 modCount++;
00675 threshold = (int) (newCapacity * loadFactor);
00676 table = newMap;
00677 for (int i = oldCapacity; i-- > 0;) {
00678 for (Entry old = oldMap[i]; old != null;) {
00679 Entry e = old;
00680 old = old.next;
00681 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
00682 e.next = newMap[index];
00683 newMap[index] = e;
00684 }
00685 }
00686 }
00687
00688
00689
00690
00691
00692
00693
00694
00695 public synchronized Object remove(Object key) {
00696 Entry tab[] = table;
00697 int hash = key.hashCode();
00698 int index = (hash & 0x7FFFFFFF) % tab.length;
00699 for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) {
00700 if ((e.hash == hash) && e.key == key) {
00701 modCount++;
00702 if (prev != null) {
00703 prev.next = e.next;
00704 } else {
00705 tab[index] = e.next;
00706 }
00707 count--;
00708 Object oldValue = e.value;
00709 e.value = null;
00710 return oldValue;
00711 }
00712 }
00713 return null;
00714 }
00715
00716
00717
00718
00719
00720 public int size() {
00721 return count;
00722 }
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734 public synchronized String toString() {
00735 int max = size() - 1;
00736 StringBuffer buf = new StringBuffer();
00737 Iterator it = entrySet().iterator();
00738 buf.append("{");
00739 for (int i = 0; i <= max; i++) {
00740 Entry e = (Entry) (it.next());
00741 buf.append(e.key + "=" + e.value);
00742 if (i < max)
00743 buf.append(", ");
00744 }
00745 buf.append("}");
00746 return buf.toString();
00747 }
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757 public Collection values() {
00758 if (values == null)
00759 values = Collections.synchronizedCollection(new ValueCollection());
00760 return values;
00761 }
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException {
00773
00774 s.defaultWriteObject();
00775
00776
00777 s.writeInt(table.length);
00778 s.writeInt(count);
00779 for (int index = table.length - 1; index >= 0; index--) {
00780 Entry entry = table[index];
00781 while (entry != null) {
00782 s.writeObject(entry.key);
00783 s.writeObject(entry.value);
00784 entry = entry.next;
00785 }
00786 }
00787 }
00788 }