1 11 package org.eclipse.core.internal.preferences; 12 13 import org.eclipse.core.internal.preferences.StringPool; 14 15 26 public abstract class ImmutableMap implements Cloneable { 27 static class ArrayMap extends ImmutableMap { 28 private static final float LOAD_FACTOR = 0.45f; 29 32 private int elementSize; 33 34 37 private String [] keyTable; 38 39 private int threshold; 40 private String [] valueTable; 41 42 ArrayMap(int size) { 43 this.elementSize = 0; 44 int tableLen = 1; 46 while (tableLen < size) 47 tableLen *= 2; 48 this.keyTable = new String [tableLen]; 49 this.valueTable = new String [tableLen]; 50 this.threshold = (int) (tableLen * LOAD_FACTOR); 51 } 52 53 public String get(String key) { 54 int lengthMask = keyTable.length - 1; 55 int index = key.hashCode() & lengthMask; 56 String currentKey; 57 while ((currentKey = keyTable[index]) != null) { 58 if (currentKey.equals(key)) 59 return valueTable[index]; 60 index = (index + 1) & lengthMask; 61 } 62 return null; 63 } 64 65 72 protected void internalPut(String key, String value) { 73 int lengthMask = keyTable.length - 1; 74 int index = key.hashCode() & lengthMask; 75 String currentKey; 76 while ((currentKey = keyTable[index]) != null) { 77 if (currentKey.equals(key)) { 78 valueTable[index] = value; 79 return; 80 } 81 index = (index + 1) & lengthMask; 82 } 83 keyTable[index] = key; 84 valueTable[index] = value; 85 ++elementSize; 86 } 87 88 91 public String [] keys() { 92 if (elementSize == 0) 93 return EMPTY_STRING_ARRAY; 94 String [] result = new String [elementSize]; 95 int next = 0; 96 for (int i = 0; i < keyTable.length; i++) 97 if (keyTable[i] != null) 98 result[next++] = keyTable[i]; 99 return result; 100 } 101 102 public ImmutableMap put(String key, String value) { 103 ArrayMap result; 104 final int oldLen = keyTable.length; 105 if (elementSize + 1 > threshold) { 106 String currentKey; 108 result = new ArrayMap(oldLen * 2); 109 for (int i = oldLen; --i >= 0;) 110 if ((currentKey = keyTable[i]) != null) 111 result.internalPut(currentKey, valueTable[i]); 112 } else { 113 result = new ArrayMap(oldLen); 114 System.arraycopy(this.keyTable, 0, result.keyTable, 0, this.keyTable.length); 115 System.arraycopy(this.valueTable, 0, result.valueTable, 0, this.valueTable.length); 116 result.elementSize = this.elementSize; 117 } 118 result.internalPut(key, value); 119 return result; 120 } 121 122 public ImmutableMap removeKey(String key) { 123 final int lengthMask = keyTable.length - 1; 124 int index = key.hashCode() & lengthMask; 125 String currentKey; 126 while ((currentKey = keyTable[index]) != null) { 127 if (currentKey.equals(key)) { 128 if (elementSize <= 1) 129 return EMPTY; 130 ImmutableMap result = createMap((int) (elementSize / LOAD_FACTOR)); 132 for (int i = 0; i < index; i++) 133 if ((currentKey = keyTable[i]) != null) 134 result.internalPut(currentKey, valueTable[i]); 135 for (int i = index + 1; i <= lengthMask; i++) 136 if ((currentKey = keyTable[i]) != null) 137 result.internalPut(currentKey, valueTable[i]); 138 return result; 139 } 140 index = (index + 1) & lengthMask; 141 } 142 return this; 143 } 144 145 148 public void shareStrings(StringPool set) { 149 String [] array = keyTable; 151 if (array == null) 152 return; 153 for (int i = 0; i < array.length; i++) { 154 String o = array[i]; 155 if (o != null) 156 array[i] = set.add(o); 157 } 158 array = valueTable; 159 if (array == null) 160 return; 161 for (int i = 0; i < array.length; i++) { 162 String o = array[i]; 163 if (o != null) 164 array[i] = set.add(o); 165 } 166 } 167 168 public int size() { 169 return elementSize; 170 } 171 172 } 173 174 static class EmptyMap extends ImmutableMap { 175 public String get(String value) { 176 return null; 177 } 178 179 public ImmutableMap removeKey(String key) { 180 return this; 181 } 182 183 protected void internalPut(String key, String value) { 184 throw new IllegalStateException (); } 186 187 public String [] keys() { 188 return EMPTY_STRING_ARRAY; 189 } 190 191 public ImmutableMap put(String key, String value) { 192 ImmutableMap result = createMap(4); 193 result.internalPut(key, value); 194 return result; 195 } 196 197 public int size() { 198 return 0; 199 } 200 } 201 202 206 public static final ImmutableMap EMPTY = new EmptyMap(); 207 208 protected static final String [] EMPTY_STRING_ARRAY = new String [0]; 209 210 216 public abstract String get(String key); 217 218 protected static ImmutableMap createMap(int i) { 219 if (i <= 0) 220 return EMPTY; 221 return new ArrayMap(i); 222 } 223 224 231 protected abstract void internalPut(String key, String value); 232 233 236 public abstract String [] keys(); 237 238 246 public abstract ImmutableMap put(String key, String value); 247 248 254 public abstract ImmutableMap removeKey(String key); 255 256 259 public void shareStrings(StringPool set) { 260 } 261 262 266 public abstract int size(); 267 268 public String toString() { 269 StringBuffer s = new StringBuffer (); 270 String [] keys = keys(); 271 for (int i = 0, length = keys.length; i < length; i++) 272 s.append(keys[i]).append(" -> ").append(get(keys[i])).append("\n"); return s.toString(); 274 } 275 } 276 | Popular Tags |