/** * Resizes the map. * * <p>This method implements the basic rehashing strategy, and may be overriden by subclasses * implementing different rehashing strategies (e.g., disk-based rehashing). However, you should * not override this method unless you understand the internal workings of this class. * * @param newN the new size */ @SuppressWarnings("unchecked") protected void rehash(final int newN) { int i = 0, pos; final boolean used[] = this.used; K k; final K key[] = this.key; final char value[] = this.value; final int newMask = newN - 1; final K newKey[] = (K[]) new Object[newN]; final char newValue[] = new char[newN]; final boolean newUsed[] = new boolean[newN]; for (int j = size; j-- != 0; ) { while (!used[i]) i++; k = key[i]; pos = (it.unimi.dsi.fastutil.HashCommon.murmurHash3(strategy.hashCode((K) (k)))) & newMask; while (newUsed[pos]) pos = (pos + 1) & newMask; newUsed[pos] = true; newKey[pos] = k; newValue[pos] = value[i]; i++; } n = newN; mask = newMask; maxFill = maxFill(n, f); this.key = newKey; this.value = newValue; this.used = newUsed; }
/** * Returns a hash code for this map. * * <p>This method overrides the generic method provided by the superclass. Since <code>equals() * </code> is not overriden, it is important that the value returned by this method is the same * value as the one returned by the overriden method. * * @return a hash code for this map. */ public int hashCode() { int h = 0; for (int j = size, i = 0, t = 0; j-- != 0; ) { while (!used[i]) i++; if (this != key[i]) t = (strategy.hashCode((K) (key[i]))); t ^= (value[i]); h += t; i++; } return h; }
@SuppressWarnings("unchecked") public boolean containsKey(final Object k) { // The starting point. int pos = (it.unimi.dsi.fastutil.HashCommon.murmurHash3(strategy.hashCode((K) (k)))) & mask; // There's always an unused entry. while (used[pos]) { if ((strategy.equals((key[pos]), (K) (k)))) return true; pos = (pos + 1) & mask; } return false; }
@SuppressWarnings("unchecked") public char getChar(final Object k) { // The starting point. int pos = (it.unimi.dsi.fastutil.HashCommon.murmurHash3(strategy.hashCode((K) (k)))) & mask; // There's always an unused entry. while (used[pos]) { if ((strategy.equals((key[pos]), (K) (k)))) return value[pos]; pos = (pos + 1) & mask; } return defRetValue; }
@SuppressWarnings("unchecked") public Character remove(final Object ok) { final K k = (K) (ok); // The starting point. int pos = (it.unimi.dsi.fastutil.HashCommon.murmurHash3(strategy.hashCode((K) (k)))) & mask; // There's always an unused entry. while (used[pos]) { if ((strategy.equals((key[pos]), (K) (k)))) { size--; final char v = value[pos]; shiftKeys(pos); return (Character.valueOf(v)); } pos = (pos + 1) & mask; } return (null); }
/* * The following methods implements some basic building blocks used by * all accessors. They are (and should be maintained) identical to those used in OpenHashSet.drv. */ public char put(final K k, final char v) { // The starting point. int pos = (it.unimi.dsi.fastutil.HashCommon.murmurHash3(strategy.hashCode((K) (k)))) & mask; // There's always an unused entry. while (used[pos]) { if ((strategy.equals((key[pos]), (K) (k)))) { final char oldValue = value[pos]; value[pos] = v; return oldValue; } pos = (pos + 1) & mask; } used[pos] = true; key[pos] = k; value[pos] = v; if (++size >= maxFill) rehash(arraySize(size + 1, f)); if (ASSERTS) checkTable(); return defRetValue; }
/** * Shifts left entries with the specified hash code, starting at the specified position, and * empties the resulting free entry. * * @param pos a starting position. * @return the position cleared by the shifting process. */ protected final int shiftKeys(int pos) { // Shift entries with the same hash. int last, slot; for (; ; ) { pos = ((last = pos) + 1) & mask; while (used[pos]) { slot = (it.unimi.dsi.fastutil.HashCommon.murmurHash3(strategy.hashCode((K) (key[pos])))) & mask; if (last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos) break; pos = (pos + 1) & mask; } if (!used[pos]) break; key[last] = key[pos]; value[last] = value[pos]; } used[last] = false; key[last] = null; return last; }
public Character put(final K ok, final Character ov) { final char v = ((ov).charValue()); final K k = (ok); // The starting point. int pos = (it.unimi.dsi.fastutil.HashCommon.murmurHash3(strategy.hashCode((K) (k)))) & mask; // There's always an unused entry. while (used[pos]) { if ((strategy.equals((key[pos]), (K) (k)))) { final Character oldValue = (Character.valueOf(value[pos])); value[pos] = v; return oldValue; } pos = (pos + 1) & mask; } used[pos] = true; key[pos] = k; value[pos] = v; if (++size >= maxFill) rehash(arraySize(size + 1, f)); if (ASSERTS) checkTable(); return (null); }
@SuppressWarnings("unchecked") private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); n = arraySize(size, f); maxFill = maxFill(n, f); mask = n - 1; final K key[] = this.key = (K[]) new Object[n]; final char value[] = this.value = new char[n]; final boolean used[] = this.used = new boolean[n]; K k; char v; for (int i = size, pos = 0; i-- != 0; ) { k = (K) s.readObject(); v = s.readChar(); pos = (it.unimi.dsi.fastutil.HashCommon.murmurHash3(strategy.hashCode((K) (k)))) & mask; while (used[pos]) pos = (pos + 1) & mask; used[pos] = true; key[pos] = k; value[pos] = v; } if (ASSERTS) checkTable(); }