150行实现HashMap核心代码

简易实现HashMap核心代码

实现效果:模拟HashMap的存入和取出

HashMap底层存储的数据结构在这里插入图片描述

实现步骤
1).创建SimpleHashMap类(模拟HashMap)
2).构建SimpleHashMap类的内部类HashNode(为HashMap的一个桶)
3).定义成员变量ArrayList<HashNode> bucketArray为桶数组
4).定义成员变量int numBuckets记录桶的个数
5).定义成员变量int size记录HashMap中有效元素个数
6).成员方法…

一:定义链表中节点类型

	class HashNode{
		private Object key;
		private Object value;
		private HashNode next;
		public HashNode(Object key, Object value) {
			this.key = key;
			this.value = value;
			}
 	}

二:定义散列表(桶数组)

   private ArrayList<HashNode> bucketArray;

三:定义桶的个数

   private int numBuckets;

四:定义size记录有效元素个数

   private int size;

五:通过构造方法对散列表初始化

   public SimpleHashMap(int nunBuckets) {
   		this.numBuckets=nunBuckets;
   		bucketArray=new ArrayList<>();
   		for (int i = 0; i <nunBuckets; i++) {
   			bucketArray.add(null);
   		}
   	}

六:定义一个散裂函数:用于计算hash值

   public int hash(Object key) {
   		int hashCode=key.hashCode();
   		int index=hashCode%numBuckets;
   		return index;
   	}

七:核心方法一:定义数据添加函数

	public void put(Object key,Object value) {
			// 1.基于key获取其散裂值(下标值)
			int index=hash(key);
			// 2.获取散裂表中对桶对象(链表节点)
			HashNode head=bucketArray.get(index);
			// 3.检测链表中是否有key相同对元素,key相同值覆盖
			while(head!=null) {
				// key 值相同值覆盖
				if(head.key.equals(key)) {
					head.value=value;
					return;
				}
				head=head.next;
			}
	
			// 4.添加新的key/value到桶中
			// 4.1获取指定下标对应的桶对象的head节点
			head=bucketArray.get(index);
			// 4.2创建新的node节点
			HashNode newNode=new HashNode(key, value);
			// 4.3将新节点设置为当前桶中的头节点
			newNode.next=head;
			// 4.4将指定index位置的头节点设置为新的头节点
			bucketArray.set(index, newNode);
			// 4.5执行size++操作
			size++;
	
			// 5.对散列表进行扩容设计  *** 0.8为加载因子
			if((1.0*size)/numBuckets>=0.8) {
				ArrayList<HashNode>temp=bucketArray;
				numBuckets=numBuckets*2;  // 将桶个数设置为原有桶个数的2倍
				bucketArray=new ArrayList<>();	// 新的散列表
				for (int i = 0; i < numBuckets; i++) {
					bucketArray.add(null);
				}
				size=0;
				// 将原有散列表中的数据拷贝到新的列表中
				for (HashNode headNode : temp) {
					while(headNode !=null) {
						put(headNode.key,headNode.value);
						headNode=headNode.next;
					}
	
				}
			}
		}

八:核心方法二:基于key删除指定元素value

	public Object remove(Object key) {
			// 1.对key进行散裂求值
			int index=hash(key);
			// 2.获取index对应对桶
			HashNode head=bucketArray.get(index);
			// 3.在桶寻找key对应对节点,然后进行删除操作
			HashNode prev=null;
			while(head!=null) {
				if(head.key.equals(key)) {
					break;
				}
				prev=head;
				head=head.next;
			}
			if(head==null)
				return null;
			if(prev!=null) {
				prev.next=head.next;
			}else {
				bucketArray.set(index, head.next);
			}
			size--;
			return head.value;
		}

九:核心方法三:根据key获取value值

   public Object get(Object key) {
   		// 1.对key进行散裂求值
   		int index=hash(key);
   		// 2.获取index对应对桶
   		HashNode head=bucketArray.get(index);
   		// 3.获取key对应对value值
   		while(head!=null) {
   			if(head.key.equals(key)) {
   				return head.value;
   			}
   			head=head.next;
   		}
   		return null;
   	}

十:计算散列表中有效元素的方法

	public int size() {
			return size;
	}

进行测试:

	public static void main(String[] args) {
   	SimpleHashMap map=new SimpleHashMap(2);
   	map.put("this", 1);
   	map.put("coder", 2);
   	map.put("this", 3);
   	System.out.println(map.size);
   	System.out.println(map.get("this"));
   	System.out.println(map.get("coder"));
   	map.remove("this");
   	System.out.println(map.size);
   	System.out.println(map.get("this"));
   }

散裂(Hash)基本面试分析:

!:如何对散裂(Hash)函数进行设计?

对与散裂函数对设计,一般要遵循如下几个元则:

· 对于给定的key,经过散裂计算,得到散列值应该是一个非负整数
·对于给定相同的key,经过同样的散列计算,一个得到的散列值
·对应不同的key,经过相同的散列计算,得到的散列值应尽量相同

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值