HashMap,哈希冲突,HashSet

1. HashMap

HashMap是键值对key-value,key不能重复,是利用hash算法实现的。

HashMap的工作原理:

我们知道在Java中最常用的两种结构是数组和模拟指针(引用),几乎所有的数据结构都可以利用这两种来组合实现,HashMap也是如此。实际上HashMap是一个“链表散列”,如下是它数据结构:最左侧是一个数组,数组中的每一个元素都是一个链表,链表的每一个元素都是entry。

HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象。

       由图可得知,HashMap是由哈希数组+链表+红黑树 组成的,也就是哈希数组,称哈希表,又称链表散列,意思就是数组不是紧密排列的。每个数组元素对应一种不同的hash值,但是不同的hash值可能会映射到数组的同一下标(即哈希冲突)。因为

n = tab.length
tab[i = (n - 1) & hash]

put(K key,V value)方法:添加键值对key-value,如果存在键key,则value覆盖oldValue,并返回oldValue。具体如下:

先通过键key,利用哈希函数hashCode()等操作,获取hash值,然后根据hash值得到映射到数组的下标,再判断key键是不是存在此下标中。

两个对象的hashCode相同,equals不一定相同;

两个对象equals相同,hashCode一定相同。

所以,重写equals()方法,一定要重写hashCode()方法。

get(Object key)方法:返回键key对应的value值,如果不存在键key,返回null。

以上两个方法都是找key,然后就直接获得附加的value值了。

 

2. 哈希冲突

如果两个不同对象映射到散列表(数组)的元素下标相同,这种现象称为hash冲突。

n = tab.length
tab[i = (n - 1) & hash]

(1)String str=new String("a"); String str2=new String("a");

键str和str2是不同的对象,但是他们的hashCode相同(hash值相同),映射到散列表的元素下标相同,所以这两个键str和str2是相同的。

(2)String str=new String("a"); String str2=new String(其他和"a"hashCode相同的字符串);

键str和str2是不同的对象,但是他们的hashCode相同(hash值相同),映射到散列表的元素下标相同,所以这两个键str和str2是相同的。

(3)String str=new String("a"); String str2=new String("q");

键str和str2是不同的对象,但是他们的hashCode不相同(hash值不相同),映射到散列表的元素下标相同,所以这两个键str和str2是相同的。

 

resize()方法:每次都将容量调整为原来的2倍,并且调整键key映射的下标。(以字符串键“a","q"为例)

比如说,初始容量为16时,键"a"和"q"映射的下标都是1; 

当初始容量调整为32时,键“a"映射的下标都是1,键“q"映射的下标都是17。

如果resize()之后不调整键”q"映射的下标(即已存在键“q"映射在1),然而下次put("q",value)时,会映射到17。那么就出现重复键“q"。

 

3. HashSet

HashSet元素不能重复,无序。

以HashSet为例,判断重复的逻辑是:
(1) 首先看hashcode是否相同,如果不同,就是不重复的
(2) 如果hashcode一样,再比较equals,如果不同,就是不重复的,否则就是重复的。

前文有提到,HashMap是key-value形式的数据结构,它的key是唯一的。而HashSet原理就是利用HashMap key唯一的特点。

public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

 

HashMap将key键值转换为Set: 调用HashMap.keySet()方法即可实现

 

 

 

 

 

 

 

 

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值