hashmap底层原理

hashmap底层原理

hashmap在Java中被频繁使用到 ,了解hashmap底层原理有利于我们理解它的存储过程及快速使用。

1.哈希表

首先我们来认识一下哈希表,哈希表:是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
 在哈希表中进行添加,删除,查找等操作,性能非常高,不考虑哈希冲突的情况下,一次定位即可完成,时间复杂度为O(1).
 在两种物理存储结构中:顺序存储结构和链式存储结构,在数组中根据下标查找某个元素,一次就可以找到元素,哈希表的主干就是数组,这样提高了查找速度。

2.hashmap的数据结构

HashMap的主干是一个Entry数组。Entry是HashMap的基本组成单元,每一个Entry包含一个object类型的key-value键值对。对采用数组+链表的形式,充分运用了数组查询快,链表插入删除快的特性。
数组:查询速度快,可以根据索引查询;但插入和删除比较困难;
链表:查询速度慢,需要遍历整个链表,但插入和删除操作比较容易。
红黑树:一种二叉树,高效的检索效率,当链表达到一定长度后,链表就会变成红黑树,当链表长度大于8的时候,将后面的数据存在二叉树中
在这里插入图片描述
自己实现简易的hashmap

import java.util.HashMap;

public class WngMap {
HashMap<String, WngMap> ap=new HashMap<>();
SxtEntry[] arr=new SxtEntry[990];
int size;

public void put(Object key,Object value){
	SxtEntry e=new SxtEntry(key, value);
	for (int i = 0; i < size; i++) {
		if(arr[i].key.equals(key)){
			arr[i].value=value;
		}
	}
	arr[size++]=e;
}
public Object get(Object key){
	for (int i = 0; i < size; i++) {
		if (arr[i].key.equals(key)) {
			return arr[i].value;
		}
	}
	return null;
}
public boolean contentKey(Object key){
	for (int i = 0; i < size; i++) {
		if(arr[i].key.equals(key)){
			return true;
		}
	}
	return false;
}

public boolean contentVlaue(Object value){
	for (int i = 0; i < size; i++) {
		if(arr[i].value.equals(value)){
			return true;
		}
	}
	return false;
}


public static void main(String[] args) {
	WngMap w=new WngMap();
	w.put("wng", "xq");
	w.put("wngsy", "ali");
	System.out.println(w.contentKey("wng"));
	System.out.println(w.get("wngsy"));
}

}

class SxtEntry{
Object key;
Object value;

public SxtEntry(Object key, Object value) {
	super();
	this.key = key;
	this.value = value;
}

}


通过例子来看一下它的存储过程,
在这里插入图片描述 如上图采用除留余数法来理解下hashmap的存储过程,对于散列表长为m的散列函数公式为:f( key ) = key mod p ( p ≤ m ) mod(取余)
  因为有10条记录,我们就先让p=10,现在要把第一个元素51放入hashmap中,51%10=1 所以把它放入数组下标为1的链表中,链表中第一个位置已经存放1,把51接着在链表中的第二个位置中。

3.哈希冲突

如果两个不同的元素通过哈希函数得出的实际存储地址相同,要进行插入的时候,发现位置已经被其他元素占用了,这就是所谓的哈希冲突,也叫哈希碰撞。哈希函数的设计至关重要,哈希函数会尽可能地保证 计算简单和散列地址分布均匀,但是,数组是一块连续的固定长度的内存空间,再好的哈希函数也不能保证得到的存储地址绝对不发生冲突。采用链地址法可以解决哈希冲突,也就是数组+链表的方式,如上面所说的它的存储过程。
在这里插入图片描述当不同对象计算出来的哈希值相同时,反生哈希冲突,链表增加一个节点,next指向下一个节点 。

4. 为什么重写equals方法需同时重写hashCode方法?

若我们把数组比作桶,桶中的list装有元素,equels直接比较的是元素。而我们在要比较桶中的元素是首先要用hashCode方法找到桶,才能用equals比较桶元素是否相等。否则可能出现取出的值为null的情况。这就是重写equals时也要同时覆盖hashcode”的原因。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值