/** * Modify is whether to make room for the new key if it doesn't exist. If a new entry is created, * the value at that position will be Double.NaN. Here's where all the magic happens. */ private int find(T key, boolean modify) { // System.out.println("find " + key + " " + modify + " " + mapType + " " + capacity()); if (mapType == MapType.SORTED_LIST) { // Binary search int i = binarySearch(key); if (i < num && keys[i] != null && key.equals(keys[i])) return i; if (modify) { if (locked) throw new RuntimeException( "Cannot make new entry for " + key + ", because map is locked"); if (num == capacity()) changeSortedListCapacity(getCapacity(num + 1, false)); // Shift everything forward for (int j = num; j > i; j--) { keys[j] = keys[j - 1]; values[j] = values[j - 1]; } num++; values[i] = Double.NaN; return i; } else return -1; } else if (mapType == MapType.HASH_TABLE) { int capacity = capacity(); int keyHash = hash(key); int i = keyHash % capacity; if (i < 0) i = -i; // Arbitrary transformation // Make sure big enough if (!locked && modify && (num > loadFactor * capacity || capacity <= num + 1)) { /*if(locked) throw new RuntimeException("Cannot make new entry for " + key + ", because map is locked");*/ switchMapType(MapType.HASH_TABLE); return find(key, modify); } // System.out.println("!!! " + keyHash + " " + capacity); if (num == capacity) throw new RuntimeException("Hash table is full: " + capacity); while (keys[i] != null && !keys[i].equals(key)) { // Collision // Warning: infinite loop if the hash table is full // (but this shouldn't happen based on the check above) i++; numCollisions++; if (i == capacity) i = 0; } if (keys[i] != null) { // Found assert key.equals(keys[i]); return i; } if (modify) { // Not found num++; values[i] = Double.NaN; return i; } else return -1; } else throw new RuntimeException("Internal bug: " + mapType); }
public void switchToHashTable() { switchMapType(MapType.HASH_TABLE); }
public void switchToSortedList() { switchMapType(MapType.SORTED_LIST); }