Java哈希表最常见的是分离链接法实现的哈希表
class SeparateChainingHashTable<AnyType>
{
//默认大小
private static final int DEFAULT_TABLE_SIZE = 101;
//默认存放表的数组
private List<AnyType> [] theLists;
//表的大小
private int currentSize;
//初始化哈希表
public SeparateChainingHashTable()
{
//调用另一个构造函数,传入初始化表的大小
this(DEFAULT_TABLE_SIZE);
}
public SeparateChainingHashTable(int size)
{
//创建一个元素是链表的数组,大小为一个质数(素数)
theLists = new LinkedList[ nextPrime(size) ];
//数组中每个成员都是一个链表
for(int i = 0; i < theLists.length; i++ )
theLists[i] = new LinkedList<>();
}
//返回传入整数的下一个质数
private static int nextPrime(int n)
{
//质数一定是个奇数
if( n % 2 == 0)
n++;
//如果n不是质数的话,判断下一个奇数
for( ; !isPrime(n); n += 2)
;
return n;
}
//判断一个数是否为质数
private static boolean isPrime(int n)
{
//2,3都是质数
if( n == 2 || n == 3)
return true;
//1和除2外的偶数都不是质数
if( n == 1 || n % 2 == 0)
return false;
//对于一个大于3的奇数,如果不是质数,那么一定有两个约数,一个大于sqrt(n),一个小于sqrt(n)
// 所以只要判断n能否被小于sqrt(n)的数整除
for(int i = 3; i * i < n; i += 2)
if(n % i == 0)
return false;
return true;
}
//makeEmpty方法:对数组内每一个位置上的链表都使用clear()方法,同时设置当前表内容大小为0
public void makeEmpty()
{
for( int i = 0; i < theLists.length; i++)
theLists[0].clear();
currentSize = 0;
}
//复写hash方法:每个元素的自定义哈希值
public static int hash(String key, int tableSize)
{
//声明自定义哈希值
int hashVal = 0;
//散列函数
for(int i = 0; i < key.length(); i++)
hashVal = 37 * hashVal +key.length();
hashVal %= tableSize;
//散列函数溢出处理
if(hashVal < 0 )
hashVal += tableSize;
return hashVal;
}
//myHash方法:根据哈希值为每个元素分配位置(角标)
private int myHash(AnyType x)
{
int hashVal = x.hashCode();
hashVal %= theLists.length;
//处理溢出
if(hashVal < 0)
hashVal += theLists.length;
return hashVal;
}
//reHash方法:增加数组大小
@SuppressWarnings("unchecked")
private void reHash()
{
List<AnyType> [] oldLists = theLists;
//创建一个二倍大小且为质数的数组
theLists = new List[ nextPrime(2 * theLists.length)];
//对新数组赋链表
for(int i = 0; i < theLists.length; i++)
theLists[i] = new LinkedList<>();
//将旧数组的链表复制到新数组里
currentSize = 0;
for(List<AnyType> list : oldLists)
for(AnyType item : list)
insert(item);
}
//contains方法
public boolean contains(AnyType x)
{
//找到在哈希表中的子链表
List<AnyType> whichList = theLists[myHash(x)];
//使用链表的contains方法
return whichList.contains(x);
}
//insert方法
public void insert(AnyType x)
{
//找到在哈希表中的子链表
List<AnyType> whichList = theLists[myHash(x)];
//判断是否重复并判断是否需要增加主链表长度
if( !whichList.contains(x) )
{
whichList.add(x);
if(++currentSize > theLists.length)
reHash();
}
}
//remove方法
public void remove(AnyType x)
{
//通过数组角标找到对应链表
List<AnyType> whichList = theLists[myHash(x)];
//链表存在该值便使用链表的移除方法,哈希表大小减一
if(whichList.contains(x))
{
whichList.remove(x);
currentSize--;
}
}
}