private void switchToMap() { ++this.modCount; final double minTableSize = 1.1 * this.list.length / this.loadFactor; int mapTableSize = 1; while (mapTableSize < minTableSize) { if (mapTableSize == MAXIMUM_CAPACITY) throw new IllegalStateException("Maximum map size exceeded"); mapTableSize <<= 1; } this.mapTable = Entry.newArray(mapTableSize); this.minKey = Integer.MAX_VALUE; this.maxKey = Integer.MIN_VALUE; for (int key = 0; key < this.list.length; ++key) { final V value = this.list[key]; if (value == null) continue; int realKey = key + this.listOffset; this.minKey = Math.min(this.minKey, realKey); this.maxKey = realKey; final int index = realKey & (mapTableSize - 1); this.mapTable[index] = new Entry<V>(realKey, value == getNullValue() ? null : value, this.mapTable[index]); } this.list = null; ++this.modCount; }
@SuppressWarnings("unchecked") @Override public IntegerMap<V> clone() { IntegerMap<V> clone; try { clone = (IntegerMap<V>) super.clone(); } catch (final CloneNotSupportedException e) { // this should never occur since we are cloneable!! throw new RuntimeException(e); } if (this.list != null) { clone.list = newArray(this.list.length); System.arraycopy(this.list, 0, clone.list, 0, this.list.length); } if (this.mapTable != null) { final Entry<V>[] newTable = Entry.newArray(this.mapTable.length); for (int j = 0; j < this.mapTable.length; ++j) { Entry<V> e = this.mapTable[j]; while (e != null) { newTable[j] = new Entry<V>(e.key, e.value, newTable[j]); e = e.next; } } clone.mapTable = newTable; } return clone; }
/** Removes all of the mappings from this map. The map will be empty after this call returns. */ @Override public void clear() { ++this.modCount; this.size = 0; if (this.list != null) { this.list = newArray(this.list.length); } else { this.mapTable = Entry.newArray(this.mapTable.length); } this.minKey = Integer.MAX_VALUE; this.maxKey = Integer.MIN_VALUE; }
/** * Rehashes the contents of this map into a new array with a larger capacity. This method is * called automatically when the number of keys in this map reaches its threshold. * * <p>If current capacity is MAXIMUM_CAPACITY, this method does not resize the map, but sets * threshold to Integer.MAX_VALUE. This has the effect of preventing future calls. * * @param newCapacity the new capacity, MUST be a power of two; must be greater than current * capacity unless current capacity is MAXIMUM_CAPACITY (in which case value is irrelevant). */ void resizeMap(final int newCapacity) { final Entry<V>[] oldTable = this.mapTable; final int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) { this.mapThreshold = Integer.MAX_VALUE; return; } final Entry<V>[] newTable = Entry.newArray(newCapacity); transferMap(newTable); this.mapTable = newTable; this.mapThreshold = (int) (newCapacity * this.loadFactor); }
/** * Constructs an empty <tt>HashMap</tt> with the specified initial capacity and load factor. * * @param initialCapacity the initial capacity * @param loadFactor the load factor * @throws IllegalArgumentException if the initial capacity is negative or the load factor is * nonpositive */ public IntegerMap( final int initialCapacity, final float loadFactor, final float switchToMapRatio, final float switchToListRatio) { if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); final int initCapacity = initialCapacity > MAXIMUM_CAPACITY ? MAXIMUM_CAPACITY : initialCapacity; if (loadFactor <= 0 || Float.isNaN(loadFactor)) // check for negative value or NaN throw new IllegalArgumentException("Illegal load factor: " + loadFactor); // Find a power of 2 >= initialCapacity int capacity = 1; while (capacity < initCapacity) capacity <<= 1; this.loadFactor = loadFactor; this.mapThreshold = (int) (capacity * loadFactor); this.mapTable = Entry.newArray(capacity); this.switchToMapRatio = switchToMapRatio; this.switchToListRatio = switchToListRatio; }