JAVA学习之路07——数据结构—>哈希表

由TreeMap实现的哈希表。由于TreeMap中K需要有可比较性,所以哈希表中的K要有可比较性。若采用链表实现哈希表,则不需要K有可比较性。

public class HashTable<K extends Comparable<K>,V> {
	//TreeMap数组,用于存放每一个tree
	private TreeMap<K, V>[] table;

	//质数,table的空间
	private int prime;
	
	//table中元素个数
	private int size;
	
	//哈希冲突的最大容忍度
	private static final int upperTol=10;
	//哈希冲突的最小容忍度
	private static final int lowerTol=2;
	
	//质数数组,table数组默认的空间
	private  int [] initCapcity={31,53,97,193,389,769,1543,3079,6151,
			12289,24593,49157,98317,196613,393241,786433,1572869,
			3145739,6291469,12582917,25165843,50331653,100663319,
			201326611,402653189,805306457,1610612741};
   
    //initCapcity数组的下标
	private int index;
	
	//构造函数
	public HashTable() {
		index=0;
		this.prime=initCapcity[index];
		//开辟prime个空间,每个空间初始化一棵树
		table=new TreeMap[prime];
		for(int i=0;i<prime;i++) {
			table[i]=new TreeMap<>();
		}
		size=0;
	}
	
	//计算散列码
	private int hash(K key) {
		return Math.abs(key.hashCode())%prime;
	}
	
	public int getSize() {
		return size;
	}
	
	//添加元素
	public void add(K key,V value) {
		int hash=hash(key);
		if(table[hash].containsKey(key)) {
			table[hash].put(key, value);
		}else{
			table[hash].put(key, value);
			size++;		
			//扩容:当元素的个数比哈希冲突最大容忍度与空间个数的乘积还要大,且数组下标不会越界,扩容
			if(size>upperTol*prime&&index+1<initCapcity.length)
				resize(initCapcity[++index]);
		}
	}
	
	//删除元素
	public V remove(K key) {
		int hash=hash(key);
		V val=null;
		if(table[hash].containsKey(key)) {
			val=table[hash].remove(key);
			size--;
		}
		//缩容
		if(size<lowerTol*initCapcity[index]&&index>0)
			resize(initCapcity[--index]);
		return val;
	}
	
	//更新元素
	public void set(K key,V val) {
		TreeMap cur=table[hash(key)];
		if(!cur.containsKey(key))
			throw new IllegalArgumentException("");
		cur.put(key, val);
	}
	
	//查找K对应的V
	public V get(K key) {
		return table[hash(key)].get(key);
	}
	
	//是否包含K
	public boolean contains(K key) {
		return table[hash(key)].containsKey(key);
	}
	
	//改变容量
	private void resize(int newPrime) {
		//开辟新的空间
		TreeMap<K,V>[] newTable=new TreeMap[newPrime];
		for(int i=0;i<newPrime;i++)
			newTable[i]=new TreeMap<>();
		this.prime=newPrime;
		//新旧table内容传递
		for(TreeMap<K,V> tab:table) {
			for(K key:tab.keySet())
				newTable[hash(key)].put(key,tab.get(key));
		}
		this.table=newTable;
	}
	
	@Override
	public String toString() {
		// TODO 自动生成的方法存根
		StringBuilder strBd=new StringBuilder();
		for(int i=0;i<table.length;i++) {
			strBd.append("HashTable["+i+"]—>"+table[i].toString()+"\n");
		} 
		return strBd.toString();
	}
}

一个简单的测试类,对table添加5000次任意的数,Value代表每个数出现的频率。

public class Test {
	public static void main(String [] args) {
		HashTable<Integer, Integer> table=new HashTable<>();
		Random random=new Random();
		for(int i=0;i<5000;i++) {
			int ran=random.nextInt(100000);
			if(table.contains(ran))
				table.set(ran, table.get(ran)+1);
			else
			table.add(ran, 1);
		}
		System.out.println(table);
	}
}

运行后部分结果如图所示:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值