1 11 package org.eclipse.jdt.internal.compiler.util; 12 import java.lang.ref.ReferenceQueue ; 13 import java.lang.ref.WeakReference ; 14 15 import org.eclipse.jdt.core.compiler.CharOperation; 16 17 20 public class WeakHashSetOfCharArray { 21 22 public class HashableWeakReference extends WeakReference { 23 public int hashCode; 24 public HashableWeakReference(char[] referent, ReferenceQueue queue) { 25 super(referent, queue); 26 this.hashCode = CharOperation.hashCode(referent); 27 } 28 public boolean equals(Object obj) { 29 if (!(obj instanceof HashableWeakReference)) return false; 30 char[] referent = (char[]) get(); 31 char[] other = (char[]) ((HashableWeakReference) obj).get(); 32 if (referent == null) return other == null; 33 return CharOperation.equals(referent, other); 34 } 35 public int hashCode() { 36 return this.hashCode; 37 } 38 public String toString() { 39 char[] referent = (char[]) get(); 40 if (referent == null) return "[hashCode=" + this.hashCode + "] <referent was garbage collected>"; return "[hashCode=" + this.hashCode + "] \"" + new String (referent) + '\"'; } 43 } 44 45 HashableWeakReference[] values; 46 public int elementSize; int threshold; 48 ReferenceQueue referenceQueue = new ReferenceQueue (); 49 50 public WeakHashSetOfCharArray() { 51 this(5); 52 } 53 54 public WeakHashSetOfCharArray(int size) { 55 this.elementSize = 0; 56 this.threshold = size; int extraRoom = (int) (size * 1.75f); 58 if (this.threshold == extraRoom) 59 extraRoom++; 60 this.values = new HashableWeakReference[extraRoom]; 61 } 62 63 68 public char[] add(char[] array) { 69 cleanupGarbageCollectedValues(); 70 int index = (CharOperation.hashCode(array) & 0x7FFFFFFF) % this.values.length; 71 HashableWeakReference currentValue; 72 while ((currentValue = this.values[index]) != null) { 73 char[] referent; 74 if (CharOperation.equals(array, referent = (char[]) currentValue.get())) { 75 return referent; 76 } 77 index = (index + 1) % this.values.length; 78 } 79 this.values[index] = new HashableWeakReference(array, this.referenceQueue); 80 81 if (++this.elementSize > this.threshold) 83 rehash(); 84 85 return array; 86 } 87 88 private void addValue(HashableWeakReference value) { 89 char[] array = (char[]) value.get(); 90 if (array == null) return; 91 int valuesLength = this.values.length; 92 int index = (value.hashCode & 0x7FFFFFFF) % valuesLength; 93 HashableWeakReference currentValue; 94 while ((currentValue = this.values[index]) != null) { 95 if (CharOperation.equals(array, (char[]) currentValue.get())) { 96 return; 97 } 98 index = (index + 1) % valuesLength; 99 } 100 this.values[index] = value; 101 102 if (++this.elementSize > this.threshold) 104 rehash(); 105 } 106 107 private void cleanupGarbageCollectedValues() { 108 HashableWeakReference toBeRemoved; 109 while ((toBeRemoved = (HashableWeakReference) this.referenceQueue.poll()) != null) { 110 int hashCode = toBeRemoved.hashCode; 111 int valuesLength = this.values.length; 112 int index = (hashCode & 0x7FFFFFFF) % valuesLength; 113 HashableWeakReference currentValue; 114 while ((currentValue = this.values[index]) != null) { 115 if (currentValue == toBeRemoved) { 116 int sameHash = index; 118 int current; 119 while ((currentValue = this.values[current = (sameHash + 1) % valuesLength]) != null && currentValue.hashCode == hashCode) 120 sameHash = current; 121 this.values[index] = this.values[sameHash]; 122 this.values[sameHash] = null; 123 this.elementSize--; 124 break; 125 } 126 index = (index + 1) % valuesLength; 127 } 128 } 129 } 130 131 public boolean contains(char[] array) { 132 return get(array) != null; 133 } 134 135 139 public char[] get(char[] array) { 140 cleanupGarbageCollectedValues(); 141 int valuesLength = this.values.length; 142 int index = (CharOperation.hashCode(array) & 0x7FFFFFFF) % valuesLength; 143 HashableWeakReference currentValue; 144 while ((currentValue = this.values[index]) != null) { 145 char[] referent; 146 if (CharOperation.equals(array, referent = (char[]) currentValue.get())) { 147 return referent; 148 } 149 index = (index + 1) % valuesLength; 150 } 151 return null; 152 } 153 154 private void rehash() { 155 WeakHashSetOfCharArray newHashSet = new WeakHashSetOfCharArray(this.elementSize * 2); newHashSet.referenceQueue = this.referenceQueue; 157 HashableWeakReference currentValue; 158 for (int i = 0, length = this.values.length; i < length; i++) 159 if ((currentValue = this.values[i]) != null) 160 newHashSet.addValue(currentValue); 161 162 this.values = newHashSet.values; 163 this.threshold = newHashSet.threshold; 164 this.elementSize = newHashSet.elementSize; 165 } 166 167 171 public char[] remove(char[] array) { 172 cleanupGarbageCollectedValues(); 173 int valuesLength = this.values.length; 174 int index = (CharOperation.hashCode(array) & 0x7FFFFFFF) % valuesLength; 175 HashableWeakReference currentValue; 176 while ((currentValue = this.values[index]) != null) { 177 char[] referent; 178 if (CharOperation.equals(array, referent = (char[]) currentValue.get())) { 179 this.elementSize--; 180 this.values[index] = null; 181 rehash(); 182 return referent; 183 } 184 index = (index + 1) % valuesLength; 185 } 186 return null; 187 } 188 189 public int size() { 190 return this.elementSize; 191 } 192 193 public String toString() { 194 StringBuffer buffer = new StringBuffer ("{"); for (int i = 0, length = this.values.length; i < length; i++) { 196 HashableWeakReference value = this.values[i]; 197 if (value != null) { 198 char[] ref = (char[]) value.get(); 199 if (ref != null) { 200 buffer.append('\"'); 201 buffer.append(ref); 202 buffer.append("\", "); } 204 } 205 } 206 buffer.append("}"); return buffer.toString(); 208 } 209 } 210 | Popular Tags |