HashMap的底层实现

  1. 默认长度16,加载因子0.75,空间换时间
  2. JDK1.8时,当链表长度超过8,链表会转变为红黑树
  3. 扩容的性能是很低的,要选择合适的容量

在这里插入图片描述
HashMap存储结构图

为什么说HashMap线程不安全?
比如有两个线程需要同时进行rehash操作,当线程A执行到Entry<K, V> oldEntry=(Entry<K, V>) entry.getNext();时,线程B开始 rehash操作,且操作完成。此时线程A的引用已经是线程B rehash操作之后的引用。当线程A继续执行,将entry处理完之后,就需要处理oldEntry,但是此时oldentry的引用已经指向了entry,之后会不停的处理entry和oldentry,就造成了循环。

HashMap接口

public interface MyMap<K, V> {
	//向集合中插入值
	public V put(K k,V v);
	//根据Key获取集合中的值
	public V get(K k);
	//获取集合元素个数
	public int size();
	
	//用于获取集合中键值对的对象
	interface Entry<K,V>{
		K getKey();
		V getValue();
		Entry<K,V> getNext();
		Entry<K,V> setNext(Entry<K,V> next);
		V setValue(V value);	
	}
}

HashMap的具体实现

public class MyHashMap<K, V> implements MyMap<K, V>{

	//Entry类型的数组,默认16,用于存放Entry数据
	private Entry<K, V> table[]=null;
	//记录hashmap的元素个数
	private int size;
	//定义初始容量16
	private static int defaultLength=16;
	//定义加载因子0.75
	private static double defaultLod=0.75;
	
	public MyHashMap() {
		table=new Entry[defaultLength];
	}
	
	
	@Override
	public V put(K k, V v) {
		
		if(size >= this.defaultLength * this.defaultLod){
			//扩容
			reHash();
		}
		int index=getIndex(k,defaultLength);
		
		//判断是不是修改
		MyMap.Entry<K, V> entry=table[index];
		while(entry!=null){
			if(entry.getKey().equals(k)){
				//修改替换
				return entry.setValue(v);
			}else{
				//循环判断下一个元素
				entry=entry.getNext();
			}
		}
		
		//创建元素并且存放在table的index上
		table[index]=new Entry<>(k,v,table[index]); 
		size++;
		return v;
	}
	
	//扩容,重新散列
	private void reHash() {
		if(size >= this.defaultLength * this.defaultLod){
			System.out.println("扩容开始");
			Entry<K, V> newTable[]=new Entry[this.defaultLength << 1];
			Entry<K, V> entry=null;
			for (int i = 0; i < table.length; i++) {
				entry=table[i];
				while(entry!=null){
					
					//进行重新散列
					int index=getIndex(entry.getKey(),newTable.length);
					
					Entry<K, V> oldEntry=(Entry<K, V>) entry.getNext();
					entry.setNext(newTable[index]);
					newTable[index]=entry;
					
					//指向下一个节点
					entry = oldEntry;
				}
			}
			table= newTable;
			this.defaultLength =  newTable.length;
			newTable=null;
			
		}
		
	}

	//哈希算法获取数组下标
	private int getIndex(K k,int length) {
		if(k==null)
			return 0;
		int hash=k.hashCode();
		//与算法
		return hash & (length-1);
	}


	@Override
	public V get(K k) {
		if(table!=null){
			int index=getIndex(k,defaultLength);
			MyMap.Entry<K, V> entry=table[index];
			
			while(entry!=null){
				if(entry.getKey().equals(k)){
					return entry.getValue();
				}else{
					entry=entry.getNext();
				}
			}
			
		}
			
		return null;
	}

	@Override
	public int size() {
		return this.size;
	}
	//Entry
	static class Entry<K, V> implements MyMap.Entry<K, V>{
		K key;
		V value;
		hashMap.MyMap.Entry<K, V> nextEntry;
		
		public Entry(K key, V value, hashMap.MyMap.Entry<K, V> nextEntry) {
			super();
			this.key = key;
			this.value = value;
			this.nextEntry = nextEntry;
		}
		@Override
		public K getKey() {
			// TODO Auto-generated method stub
			return this.key;
		}
		@Override
		public V getValue() {
			return this.value;
		}
		
		@Override
		public V setValue(V value) {
			V ov=this.value;
			this.value=value;
			return ov;
		}
		
		@Override
		public hashMap.MyMap.Entry<K, V> getNext() {
			return this.nextEntry;
		}
		@Override
		public hashMap.MyMap.Entry<K, V> setNext(hashMap.MyMap.Entry<K, V> next) {
			hashMap.MyMap.Entry<K, V>  oe=this.nextEntry;
			this.nextEntry= next;
			return oe;
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值