谈谈HashSet的存储原理及为什么重写equals必须重写hashcode方法

Posted shew

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了谈谈HashSet的存储原理及为什么重写equals必须重写hashcode方法相关的知识,希望对你有一定的参考价值。

HashSet的存储原理:

  1、将要传入的数据根据系统的hash算法得到一个hash值;

  2、根据hash值可以得出该数据在hash表中的位置;

  3、判断该位置上是否有值,没有值则把数据插入进来;如果有值则再次判断传入的值与原值是否地址或equals相同,如果相同则不存,否则通过链表的方式 存储到该位置。

如果两个对象equals,但是没有重写hashcode,就会导致集合中存储多个相等的对象!所以必须重写!

比如:

Set<Integer> set = new HashSet<Integer>();

  set.add( e );//add方法是return map.put( e , PRESENT) == null;

本质是实例化医个HashMap对象 ---->map = new HashMap<>();

然后是map.put()方法,

public V put(K key,V value)

  if(table == EMPTY_TABLE)

    inflateTable(threshold);  //此处是初始化一张哈希表,表为数组结构

  

  int hash = hash(key);  //根据key值,计算出对应的int类型的hash值

  int i = inexFor(hash,table.length):  //通过hash值在table表中得到一个存储的位置

  //判断指定下标的位置是否为空,如果为空则跳出循环,直接添加

  //否则与该位置上的链表元素一一比较,如果哈希值相同且地址或equals相同,则返回

  //否则添加进来

  for(Entry<K,V> e = table[i]; e != null; e = e.next)

    Object k ;

    //如果哈希值相等并且地址相等(需重写equals)

    if(e.hash == hash && ((k = e.key) == key || key.equals(k))

      V oldValue = e.value;

      e.value = value;

      e.recordAccess(this);

      return oldValue;

    

  

  modCount++;

  addEntry(hash, key, value, i);   //以链表的方式添加元素

  return null;

 

技术图片

以上是关于谈谈HashSet的存储原理及为什么重写equals必须重写hashcode方法的主要内容,如果未能解决你的问题,请参考以下文章

Set和HashSet LinkedHashSet

为什么重写equals()就必须重写hashCode(),什么情况下可以不重写hashCode()

总结,为什么要重写hashset的hashcode()和equals()?

重写equals就必须重写hashCode的原理分析

为什么重写equals以后还要重写hashcode

HashSet——add remove contains方法底层代码分析(hashCode equals 方法的重写)