Hashset集合底层存储位置为什么会出现链表的情况

最近新学了一遍Hashset集合,Hashset底层是由数组加链表和红黑树组成的,当数据存入时由数组长度和哈希值运算出该存入的位置,当位置重复时后来的数据挂载在老数据下形成链表结构,但是不同数据哈希值相同也就是哈希碰撞的出现概率是很小的,而数组长度是在数组中存储的数据量大于等于数组长度加载因子时才会扩容改变,那么是不是因为数组长度的改变才导致不一样的哈希值能算出一样的存储位置呢?比如4 * 250=2050?

道理很简单,hash肯定比原数据范围小(hash比原数据范围大,或者相等,那么hash的意义就没有了),那么肯定没办法做到一一映射,那么肯定会有碰撞,概率小但是也是有的,那么就要链表来处理冲突。你不能说概率小就不管了。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 帮你找了个相似的问题, 你可以看下: https://ask.csdn.net/questions/728662
  • 以下回答由chatgpt基于相关博客总结生成:

    在HashSet集合中,每个元素都有一个相应的hash code。HashSet使用该hash code来确定元素应该存储在数组中的哪个位置。当使用hashCode()方法时,会将其结果取模运算,以计算索引(即元素在数组中的位置)。如果两个元素的hashCode()结果相同,会发生哈希冲突。这种情况下,HashSet会检查这两个元素是否相等,通过equals()方法进行比较。

    如果数组中的位置已被占用,新元素将会被挂载在已有元素的下方,从而形成链表结构。这是因为HashSet使用开放寻址法解决哈希冲突。当哈希碰撞发生时,HashSet会检查数组中下一个位置是否被占用,如果没有被占用,元素将被存储在该位置;如果该位置已被占用,则继续检查下一个位置,直至找到一个空位置。

    当链表长度变得太长时,HashSet会按照一定规则将链表转换为红黑树,以提高搜索、插入和删除元素的效率。这是为了避免链表过长导致的性能问题。

    当数组长度改变时,可能会导致不同的哈希值算出相同的存储位置。这是因为改变数组长度会改变取模运算的结果,从而影响元素在数组中的存储位置。然而,这并不意味着不同哈希值一定会算出相同的存储位置。取模运算是一种散列函数,它的目的是使数据均匀地分布在数组中,尽量减少哈希冲突的发生。即使数组长度改变,hashCode()方法仍然会计算出一个不同的哈希值,以保持数据的均匀散列。

    总结来说,HashSet集合底层存储位置会出现链表的情况是因为哈希冲突发生时,元素会被挂载在已有元素的下方,形成链表结构。数组长度的改变可能会导致不同的哈希值算出相同的存储位置,但这并不意味着不同的哈希值一定会算出相同的存储位置。通过合理的散列函数和开放寻址法,HashSet可以高效地处理哈希冲突。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

感觉你说的可能有点问题:
首先HashSet其实是存在HashMap的Key里面的,所以本质上HashSet底层并没有什么链表,相同的数据也不会进入到HashSet里面
其次,可能你想说的是HashMap,哈希值是HashMap类里面有个hash(Object key)方法算出来的,里面只是使用了Object累的hashCode()方法和一些算法,后面说的如果数组如果扩增,那么位置需要重新算,那么不同哈希值的数据可能会被算到同一个位置,这个概率是有点,所以我认为hash方法里面的算法是比较重要的,应该就是减少这个概率的。