1 11 package org.eclipse.jdt.internal.core.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 static 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 valuesLength = this.values.length, 71 index = (CharOperation.hashCode(array) & 0x7FFFFFFF) % valuesLength; 72 HashableWeakReference currentValue; 73 while ((currentValue = this.values[index]) != null) { 74 char[] referent; 75 if (CharOperation.equals(array, referent = (char[]) currentValue.get())) { 76 return referent; 77 } 78 if (++index == valuesLength) { 79 index = 0; 80 } 81 } 82 this.values[index] = new HashableWeakReference(array, this.referenceQueue); 83 84 if (++this.elementSize > this.threshold) 86 rehash(); 87 88 return array; 89 } 90 91 private void addValue(HashableWeakReference value) { 92 char[] array = (char[]) value.get(); 93 if (array == null) return; 94 int valuesLength = this.values.length; 95 int index = (value.hashCode & 0x7FFFFFFF) % valuesLength; 96 HashableWeakReference currentValue; 97 while ((currentValue = this.values[index]) != null) { 98 if (CharOperation.equals(array, (char[]) currentValue.get())) { 99 return; 100 } 101 if (++index == valuesLength) { 102 index = 0; 103 } 104 } 105 this.values[index] = value; 106 107 if (++this.elementSize > this.threshold) 109 rehash(); 110 } 111 112 private void cleanupGarbageCollectedValues() { 113 HashableWeakReference toBeRemoved; 114 while ((toBeRemoved = (HashableWeakReference) this.referenceQueue.poll()) != null) { 115 int hashCode = toBeRemoved.hashCode; 116 int valuesLength = this.values.length; 117 int index = (hashCode & 0x7FFFFFFF) % valuesLength; 118 HashableWeakReference currentValue; 119 while ((currentValue = this.values[index]) != null) { 120 if (currentValue == toBeRemoved) { 121 int sameHash = index; 123 int current; 124 while ((currentValue = this.values[current = (sameHash + 1) % valuesLength]) != null && currentValue.hashCode == hashCode) 125 sameHash = current; 126 this.values[index] = this.values[sameHash]; 127 this.values[sameHash] = null; 128 this.elementSize--; 129 break; 130 } 131 if (++index == valuesLength) { 132 index = 0; 133 } 134 } 135 } 136 } 137 138 public boolean contains(char[] array) { 139 return get(array) != null; 140 } 141 142 146 public char[] get(char[] array) { 147 cleanupGarbageCollectedValues(); 148 int valuesLength = this.values.length; 149 int index = (CharOperation.hashCode(array) & 0x7FFFFFFF) % valuesLength; 150 HashableWeakReference currentValue; 151 while ((currentValue = this.values[index]) != null) { 152 char[] referent; 153 if (CharOperation.equals(array, referent = (char[]) currentValue.get())) { 154 return referent; 155 } 156 if (++index == valuesLength) { 157 index = 0; 158 } 159 } 160 return null; 161 } 162 163 private void rehash() { 164 WeakHashSetOfCharArray newHashSet = new WeakHashSetOfCharArray(this.elementSize * 2); newHashSet.referenceQueue = this.referenceQueue; 166 HashableWeakReference currentValue; 167 for (int i = 0, length = this.values.length; i < length; i++) 168 if ((currentValue = this.values[i]) != null) 169 newHashSet.addValue(currentValue); 170 171 this.values = newHashSet.values; 172 this.threshold = newHashSet.threshold; 173 this.elementSize = newHashSet.elementSize; 174 } 175 176 180 public char[] remove(char[] array) { 181 cleanupGarbageCollectedValues(); 182 int valuesLength = this.values.length; 183 int index = (CharOperation.hashCode(array) & 0x7FFFFFFF) % valuesLength; 184 HashableWeakReference currentValue; 185 while ((currentValue = this.values[index]) != null) { 186 char[] referent; 187 if (CharOperation.equals(array, referent = (char[]) currentValue.get())) { 188 this.elementSize--; 189 this.values[index] = null; 190 rehash(); 191 return referent; 192 } 193 if (++index == valuesLength) { 194 index = 0; 195 } 196 } 197 return null; 198 } 199 200 public int size() { 201 return this.elementSize; 202 } 203 204 public String toString() { 205 StringBuffer buffer = new StringBuffer ("{"); for (int i = 0, length = this.values.length; i < length; i++) { 207 HashableWeakReference value = this.values[i]; 208 if (value != null) { 209 char[] ref = (char[]) value.get(); 210 if (ref != null) { 211 buffer.append('\"'); 212 buffer.append(ref); 213 buffer.append("\", "); } 215 } 216 } 217 buffer.append("}"); return buffer.toString(); 219 } 220 } 221 | Popular Tags |