手写HashMap简化版

package cn.map;

import java.util.ArrayList;
import java.util.List;

public class MyHashMap<K, V> implements MyMap<K,V>{
	
	//数组表默认长度
	private static int defaultLength = 16;
	
	//负载因子
	private static double defaultLoader = 0.75;
	
	//存储元素的表
	private Entry<K, V>[] table = null;
	
	//数组中存取元素的个数
	private int size = 0;
	
	public MyHashMap() {
		this.table = new Entry[defaultLength];
	}
	
	public MyHashMap(int length, double loader) {
		this.defaultLength = length;
		this.defaultLoader = loader;
		this.table = new Entry[defaultLength];
	}
	
	
	//这是一个hash算法,根据K对表的长度取余,得到的值就是表的下标
	private int getIndex(K k) {
		int m = defaultLength;
		
		//得到的可能是一个负值
		int index = k.hashCode() % m;
		
		return index >= 0 ? index : -index;
	}
	
	@Override
	public V put(K k, V v) {
		
		if(size >= defaultLength * defaultLoader) {
			upSize();
		}
		
		//根据k拿到存储位置,hash计算
		int index = getIndex(k);
		
		Entry<K, V> entry = table[index];
		
		if(entry == null) {
			size++;
		} 
		table[index] = newEntry(k, v, entry);	
		return table[index].getValue();
	}
	
	//扩容方法,每次扩充一倍
	private void upSize() {
		Entry<K,V>[] newTable = new Entry[2 * defaultLength];
		//数组长度翻倍,元素在表中的位置也要随之改变
		reHash(newTable);
	}
	
	//新建数组,然后把旧数组中的元素再次进行hash
	private void reHash(Entry<K,V>[] newTable) {
		List<Entry<K,V>> list = new ArrayList<>();
		
		//把旧表中的全部数据放到list中
		for(int i = 0; i < table.length; i++) {
			if(table[i] == null) {
				continue;
			}
			addEntryByNext(table[i], list);
		}
		
		//再次hash
		if(list.size() > 0) {
			size = 0;
			defaultLength *= 2;
			table = newTable;
			
			for(Entry<K,V> entry : list) {
				if(entry.next != null) {
					//将原始链表结构全部解体
					entry.next = null;
				}
				put(entry.getKey(),entry.getValue());
			}
		}
	}
	
	//将entry所在链表数据全部放入指定list中
	private void addEntryByNext(Entry<K,V> entry, List<Entry<K,V>> list) {
		if(entry != null && entry.next != null) {
			list.add(entry);
			addEntryByNext(entry.next, list);
		} else {
			list.add(entry);
		}
	}
	private Entry<K, V> newEntry(K k, V v, Entry<K,V> next) {
		return new Entry(k, v, next);
	}

	@Override
	public V get(K k) {
		int index = getIndex(k);
		
		if(table[index] == null) {
			return null;
		}
		
		return findEntryByEqKey(k,table[index]);
	}

	//根据key在entry链表中查找对应元素的value
	private V findEntryByEqKey(K k, Entry<K, V> entry) {
		if(k == entry.getKey() || k.equals(entry.getKey())) {
			return entry.getValue();
		} else {
			if(entry.next != null) {
				return findEntryByEqKey(k, entry.next);
			}
		}
		return null;
	}

	@Override
	public int size() {
		// TODO Auto-generated method stub
		return 0;
	}

	class Entry<K, V> implements MyMap.Entry<K, V> {
		
		K k;
		
		V v;
		
		//next指针,指向下一个链表数据
		Entry<K, V> next;
		
		public Entry(K k, V v, Entry<K, V> next) {
			this.k = k;
			this.v = v;
			this.next = next;
		}
		
		@Override
		public K getKey() {
			
			return this.k;
		}

		@Override
		public V getValue() {
	
			return this.v;
		}
		
	}
	
}
JDK中的HashMap具有更加复杂的位运算,大大提高了元素的命中率,所以效率会比简化版HashMap快,但是HashMapd的基本原理就是这样
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值