1 11 package org.eclipse.core.internal.utils; 12 13 14 17 18 public class KeyedHashSet { 19 public interface KeyedElement { 20 21 public boolean compare(KeyedElement other); 22 23 public Object getKey(); 24 25 public int getKeyHashCode(); 26 } 27 28 protected static final int MINIMUM_SIZE = 7; 29 private int capacity; 30 protected int elementCount = 0; 31 protected KeyedElement[] elements; 32 protected boolean replace; 33 34 public KeyedHashSet(int capacity) { 35 this(capacity, true); 36 } 37 38 public KeyedHashSet(int capacity, boolean replace) { 39 elements = new KeyedElement[Math.max(MINIMUM_SIZE, capacity * 2)]; 40 this.replace = replace; 41 this.capacity = capacity; 42 } 43 44 49 public boolean add(KeyedElement element) { 50 int hash = hash(element); 51 52 for (int i = hash; i < elements.length; i++) { 54 if (elements[i] == null) { 55 elements[i] = element; 56 elementCount++; 57 if (shouldGrow()) 59 expand(); 60 return true; 61 } 62 if (elements[i].compare(element)) { 63 if (replace) 64 elements[i] = element; 65 return replace; 66 } 67 } 68 69 for (int i = 0; i < hash - 1; i++) { 71 if (elements[i] == null) { 72 elements[i] = element; 73 elementCount++; 74 if (shouldGrow()) 76 expand(); 77 return true; 78 } 79 if (elements[i].compare(element)) { 80 if (replace) 81 elements[i] = element; 82 return replace; 83 } 84 } 85 86 expand(); 88 return add(element); 89 } 90 91 public void clear() { 92 elements = new KeyedElement[Math.max(MINIMUM_SIZE, capacity * 2)]; 93 elementCount = 0; 94 } 95 96 100 protected void expand() { 101 KeyedElement[] oldElements = elements; 102 elements = new KeyedElement[elements.length * 2]; 103 104 int maxArrayIndex = elements.length - 1; 105 for (int i = 0; i < oldElements.length; i++) { 106 KeyedElement element = oldElements[i]; 107 if (element != null) { 108 int hash = hash(element); 109 while (elements[hash] != null) { 110 hash++; 111 if (hash > maxArrayIndex) 112 hash = 0; 113 } 114 elements[hash] = element; 115 } 116 } 117 } 118 119 123 public KeyedElement getByKey(Object key) { 124 if (elementCount == 0) 125 return null; 126 int hash = keyHash(key); 127 128 for (int i = hash; i < elements.length; i++) { 130 KeyedElement element = elements[i]; 131 if (element == null) 132 return null; 133 if (element.getKey().equals(key)) 134 return element; 135 } 136 137 for (int i = 0; i < hash - 1; i++) { 139 KeyedElement element = elements[i]; 140 if (element == null) 141 return null; 142 if (element.getKey().equals(key)) 143 return element; 144 } 145 146 return null; 148 } 149 150 private int hash(KeyedElement key) { 151 return Math.abs(key.getKeyHashCode()) % elements.length; 152 } 153 154 private int keyHash(Object key) { 155 return Math.abs(key.hashCode()) % elements.length; 156 } 157 158 162 protected void rehashTo(int anIndex) { 163 164 int target = anIndex; 165 int index = anIndex + 1; 166 if (index >= elements.length) 167 index = 0; 168 KeyedElement element = elements[index]; 169 while (element != null) { 170 int hashIndex = hash(element); 171 boolean match; 172 if (index < target) 173 match = !(hashIndex > target || hashIndex <= index); 174 else 175 match = !(hashIndex > target && hashIndex <= index); 176 if (match) { 177 elements[target] = element; 178 target = index; 179 } 180 index++; 181 if (index >= elements.length) 182 index = 0; 183 element = elements[index]; 184 } 185 elements[target] = null; 186 } 187 188 public boolean remove(KeyedElement toRemove) { 189 if (elementCount == 0) 190 return false; 191 192 int hash = hash(toRemove); 193 194 for (int i = hash; i < elements.length; i++) { 195 KeyedElement element = elements[i]; 196 if (element == null) 197 return false; 198 if (element.compare(toRemove)) { 199 rehashTo(i); 200 elementCount--; 201 return true; 202 } 203 } 204 205 for (int i = 0; i < hash - 1; i++) { 206 KeyedElement element = elements[i]; 207 if (element == null) 208 return false; 209 if (element.compare(toRemove)) { 210 rehashTo(i); 211 elementCount--; 212 return true; 213 } 214 } 215 return false; 216 } 217 218 private boolean shouldGrow() { 219 return elementCount > elements.length * 0.75; 220 } 221 222 public int size() { 223 return elementCount; 224 } 225 226 public String toString() { 227 StringBuffer result = new StringBuffer (100); 228 result.append('{'); 229 boolean first = true; 230 for (int i = 0; i < elements.length; i++) { 231 if (elements[i] != null) { 232 if (first) 233 first = false; 234 else 235 result.append(", "); result.append(elements[i]); 237 } 238 } 239 result.append('}'); 240 return result.toString(); 241 } 242 } 243 | Popular Tags |