黑马程序员技术交流社区

标题: 对于HashSet的保持元素唯一性的进一步理解 [打印本页]

作者: 1453149997    时间: 2014-4-4 17:16
标题: 对于HashSet的保持元素唯一性的进一步理解
本帖最后由 1453149997 于 2014-4-5 14:32 编辑



如果按照老师的结论:即“如果元素的hashCode值不同,不会调用equals”,那么请问,集合是怎么知道要插入的元素A的哈希值和集合中的某个元素的哈希值不一样的?
有两种猜想:
(1)调用集合中的每个元素的hashcode的方法,然后用A的哈希值和每个元素的哈希值比较,但是这样的做法效率很低,显然违背了HashSet设计的初衷(即查询效率高)
(2)HashSet被划分为不同的区域,每一段都有一个哈希值来代表;HashSet创建之初,并没有被划分区域,只有有元素存入时,才需要根据元素的哈希值来确定分配存储区域;后续元素插入时,要根据某个哈希值是否存在来确定是否需要分配新的空间;
   如果(1)不成立,那么在HashSet中存在了另一个集合B,用来存储哈希值;当A需要插入时,用A的哈希值和B中的元素比较,可以快速确定是否存在和A哈希值相同的元素,如果有,则调用equals方法和此区域的所有元素比较;如果没有,则HashSet根据哈希值另外分配空间,存储新的元素

请问我的理解合理吗?

作者: 罗安迪    时间: 2014-4-4 17:40
本帖最后由 罗安迪 于 2014-4-4 17:42 编辑

1,对于set,存入和取出是无序的,因为他们根据哈希值被存在不同的区域当中。

2,集合B应该理解为 哈希表。就相当于你把元素按哈希值存到了不同的房间,存进去后在同一张纸上写下房间号和存入元素,那么在查找的时候自然就可以直接用表格去查找,而不用进入房间,所以速度快了。

所以你的1和2的理解都是对的~除了调用时查询会慢(事实是会快)。

另外:其次set的底层是map,set集合来自于map。所以在理解上,你完全可以认为
作者: 向阳泪无痕    时间: 2014-4-4 18:14
为什么知道 HashCode 值不同,这不就是让你复写这个功能么,你复写这个功能后,这个相不相同,由你来规定。
作者: haixian    时间: 2014-4-4 19:32
不合理,哈西值是通过hash算法散列运算出来的,。不是保存在一个集合中的。
作者: 李洋-    时间: 2014-4-4 19:47
看到你的截图,感觉像是刘意老师总结的是吗
作者: 1453149997    时间: 2014-4-5 14:29
不是,是毕向东老师的
作者: 1453149997    时间: 2014-4-5 14:30
李洋- 发表于 2014-4-4 19:47
看到你的截图,感觉像是刘意老师总结的是吗

是毕向东老师的
作者: 李洋-    时间: 2014-4-12 18:48
1453149997 发表于 2014-4-5 14:30
是毕向东老师的

你是云九的嘛?
作者: 李程    时间: 2014-4-12 18:54
你看下毕老师的讲解和我的理解
11,HashSet心得
对象的地址值相同,那么哈希值一定相同,如果地址值不同,那么哈希值也有可能相同,在哈希值不相同的时候,在HashSet容器中存储的时候就直接存了,如果哈希值相同的时候,就再比较两个对象是否相同,这个时候就是比较两个对象的地址值是否相同了(后面这句话是我自己的猜测,因为equals比较的就是地址,如果复写了equals的话那就另当别论了,总之调用的是equals方法),如果两个对象也相同,那么就不存储,如果对象不同,那么就在同一个哈希值下链式或者顺序存储两个对象。

12,HashSet是如何保证元素唯一性的呢
是通过元素的两个方法,hashCoed和equals来完成:如果元素的HashCode值相同,才会判断equals是否为真;如果元素的HashCode值不相同,才会调用equals,所以建立一个有针对性的HashCode才比较高效。
所以在实际开发过程中,一旦自己定义或者描述一个新的事物,即建立一个类的时候,如果其对象会往集合里面存储,那一般就会复写equals方法和hashCode方法
注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法
作者: 无此姓名    时间: 2014-4-13 18:56
关于这个问题楼主可以看张孝祥老师的基础加强视频-26. 我截了几张图:




作者: chensc    时间: 2014-6-5 08:10
学习学习!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2