📄 basehashmap.java
字号:
/* Copyright (c) 2001-2005, The HSQL Development Group * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the HSQL Development Group nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */package org.hsqldb.store;import java.util.NoSuchElementException;import org.hsqldb.lib.ArrayCounter;public class BaseHashMap {/** * Base class for hash tables or sets. The exact type of the structure is * defined by the constructor. Each instance has at least a keyTable array * and a HashIndex instance for looking up the keys into this table. Instances * that are maps also have a valueTable the same size as the keyTable. * * Special getOrAddXXX() methods are used for object maps in some subclasses. * * @author fredt@users * @version 1.8.0 * @since 1.7.2 *//* data store: keys: {array of primitive | array of object} values: {none | array of primitive | array of object} same size as keys objects support : hashCode(), equals() implemented types of keyTable: {objectKeyTable: variable size Object[] array for keys | intKeyTable: variable size int[] for keys | longKeyTable: variable size long[] for keys } implemented types of valueTable: {objectValueTable: variable size Object[] array for values | intValueTable: variable size int[] for values | longValueTable: variable size long[] for values} valueTable does not exist for sets or for object pools hash index: hashTable: fixed size int[] array for hash lookup into keyTable linkTable: pointer to the next key ; size equal or larger than hashTable but equal to the valueTable access count table: {none | variable size int[] array for access count} same size as xxxKeyTable*/ // boolean isIntKey; boolean isLongKey; boolean isObjectKey; boolean isNoValue; boolean isIntValue; boolean isLongValue; boolean isObjectValue; // protected HashIndex hashIndex; // protected int[] intKeyTable; protected Object[] objectKeyTable; protected long[] longKeyTable; // protected int[] intValueTable; protected Object[] objectValueTable; protected long[] longValueTable; // int accessMin; int accessCount; int[] accessTable; // final float loadFactor; final int initialCapacity; int threshold; int maxCapacity; protected int purgePolicy = NO_PURGE; protected boolean minimizeOnEmpty; // boolean hasZeroKey; int zeroKeyIndex = -1; // keyOrValueTypes protected static final int noKeyOrValue = 0; protected static final int intKeyOrValue = 1; protected static final int longKeyOrValue = 2; protected static final int objectKeyOrValue = 3; // purgePolicy protected static final int NO_PURGE = 0; protected static final int PURGE_ALL = 1; protected static final int PURGE_HALF = 2; protected static final int PURGE_QUARTER = 3; protected BaseHashMap(int initialCapacity, float loadFactor, int keyType, int valueType, boolean hasAccessCount) throws IllegalArgumentException { if (initialCapacity <= 0 || loadFactor <= 0.0) { throw new IllegalArgumentException(); } this.loadFactor = loadFactor; this.initialCapacity = initialCapacity; threshold = initialCapacity; if (threshold < 3) { threshold = 3; } int hashtablesize = (int) (initialCapacity * loadFactor); if (hashtablesize < 3) { hashtablesize = 3; } hashIndex = new HashIndex(hashtablesize, initialCapacity, true); int arraySize = threshold; if (keyType == BaseHashMap.intKeyOrValue) { isIntKey = true; intKeyTable = new int[arraySize]; } else if (keyType == BaseHashMap.objectKeyOrValue) { isObjectKey = true; objectKeyTable = new Object[arraySize]; } else { isLongKey = true; longKeyTable = new long[arraySize]; } if (valueType == BaseHashMap.intKeyOrValue) { isIntValue = true; intValueTable = new int[arraySize]; } else if (valueType == BaseHashMap.objectKeyOrValue) { isObjectValue = true; objectValueTable = new Object[arraySize]; } else if (valueType == BaseHashMap.longKeyOrValue) { isLongValue = true; longValueTable = new long[arraySize]; } else { isNoValue = true; } if (hasAccessCount) { accessTable = new int[arraySize]; } } protected int getLookup(Object key, int hash) { int lookup = hashIndex.getLookup(hash); Object tempKey; for (; lookup >= 0; lookup = hashIndex.getNextLookup(lookup)) { tempKey = objectKeyTable[lookup]; if (key.equals(tempKey)) { return lookup; } } return lookup; } protected int getLookup(int key) { int lookup = hashIndex.getLookup(key); int tempKey; for (; lookup >= 0; lookup = hashIndex.getNextLookup(lookup)) { tempKey = intKeyTable[lookup]; if (key == tempKey) { return lookup; } } return lookup; } protected int getLookup(long key) { int lookup = hashIndex.getLookup((int) key); long tempKey; for (; lookup >= 0; lookup = hashIndex.getNextLookup(lookup)) { tempKey = longKeyTable[lookup]; if (key == tempKey) { return lookup; } } return lookup; } /** * generic method for adding or removing keys */ protected Object addOrRemove(long longKey, long longValue, Object objectKey, Object objectValue, boolean remove) { int hash = (int) longKey; if (isObjectKey) { if (objectKey == null) { return null; } hash = objectKey.hashCode(); } int index = hashIndex.getHashIndex(hash); int lookup = hashIndex.hashTable[index]; int lastLookup = -1; Object returnValue = null; for (; lookup >= 0; lastLookup = lookup, lookup = hashIndex.getNextLookup(lookup)) { if (isObjectKey) { if (objectKeyTable[lookup].equals(objectKey)) { break; } } else if (isIntKey) { if (longKey == intKeyTable[lookup]) { break; } } else if (isLongKey) { if (longKey == longKeyTable[lookup]) { break; } } } if (lookup >= 0) { if (remove) { if (isObjectKey) { objectKeyTable[lookup] = null; } else { if (longKey == 0) { hasZeroKey = false; zeroKeyIndex = -1; } if (isIntKey) { intKeyTable[lookup] = 0; } else { longKeyTable[lookup] = 0; } } if (isObjectValue) { returnValue = objectValueTable[lookup]; objectValueTable[lookup] = null; } else if (isIntValue) { intValueTable[lookup] = 0; } else if (isLongValue) { longValueTable[lookup] = 0; } hashIndex.unlinkNode(index, lastLookup, lookup); if (accessTable != null) { accessTable[lookup] = 0; } if (minimizeOnEmpty && hashIndex.elementCount == 0) { rehash(initialCapacity); } return returnValue; } if (isObjectValue) { returnValue = objectValueTable[lookup]; objectValueTable[lookup] = objectValue; } else if (isIntValue) { intValueTable[lookup] = (int) longValue; } else if (isLongValue) { longValueTable[lookup] = longValue; } if (accessTable != null) { accessTable[lookup] = accessCount++; } return returnValue; } // not found if (remove) { return null; } if (hashIndex.elementCount >= threshold) { // should throw maybe, if reset returns false? if (reset()) { return addOrRemove(longKey, longValue, objectKey, objectValue, remove); } else { return null; } } lookup = hashIndex.linkNode(index, lastLookup); // type dependent block if (isObjectKey) { objectKeyTable[lookup] = objectKey; } else if (isIntKey) { intKeyTable[lookup] = (int) longKey; if (longKey == 0) { hasZeroKey = true; zeroKeyIndex = lookup; } } else if (isLongKey) { longKeyTable[lookup] = longKey; if (longKey == 0) { hasZeroKey = true; zeroKeyIndex = lookup; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -