刚看了关于hashCode的一些文章,也大致了解了hashCode的功能,但是在看文章的时候,产生了一个疑问:文章中把一个Set比做一堆桶,每个桶都有一个编号,这个编号就是hashCode。每个桶里面都装有元素。那么把一个新的元素加入到set中时,需要获取元素的hashCode,通过hashCode查找桶,然后再对桶里面的元素分别用equals进行比较,如果没有相同的元素,则填入set。问题是,如果上面的说法是正确的,那么如果有两个set,如set1和set2。当set1新增了一个元素test1后, set2再次增加test1时,也是通过test1的hashCode查询,这时就应该出现问题了啊,因为这个hashCode对应的地址已经有元素,并且equals也相同(因为都是test1)。可实际情况是set2也可以增加test1,说明没有问题。不理解中

解决方案 »

  1.   

    因为set保存的不是一个实例,只是保存了一个hashcode,通过hashcode去查找对应的对象,所以set1和set2保存了test1的hashcode,而这个hashcode都是指向test1这个实例
      

  2.   

    理解错了,hashcode本身不是用来放东西的地址,而是用来
    1:快速比较两个东西是不是一样。H一样,不一定相同,但H不一样,两者必不相同——除非你自己乱写hashCode方法
    2:快速定位hashcode和存放的位置有一定的联系。add/set/put的时候,根据hashcode算出它应该在的位置,如果当前位置有人,判断是否相同(equals),相同则覆盖,不同,说明有冲撞,利用一定的算法解决。
      

  3.   

    问题是set2要保存test1时,首先需要确认test1是不是重复元素。按文章中的做法是,首先获取test1的hashCode,再通过hashCode获取了链表,对链表做循环equals,如果相同则不加入,如果没有相同的则加入。
    按照我的做法,set1在保存test1的时候,相当于这个hashCode对应的链表里面已经有这个对象了,那么set2再做保存的时候,同样是根据test1的hashCode做的查找,不就有重复元素了吗(因为set1添加test1的时候已经对这个hashCode做了操作)?
      

  4.   

    补充一下,
    上面第二条是HashSet/Map等的工作机制,是基于第一条原理的。也就是说,存放、读取的时候,无需对所有已存在的元素进行比较
      

  5.   

    还是理解不对,不过是另一个理解不对
    set1指向是一个实例
    set2又是指向另一个实例(set1和set2的hashcode基本不一致,就算一致,equals也不会一样)
    set说的是在一个实例里,保存的元素不重复,既然是2个不同的实例,当然各有各的
      

  6.   

    楼主你这个问题是因为你没有理解HASHSET的存储结构其实HASHSET底层是用MAP去实现的,这个MAP的KEY对应每个对象的HASHCODE值,VALUE是一个链表这样,每次放入HASHSET的时候,
    1、判断HASHCODE,如果和其他的都不同直接放入SET中那个HASHCODE 为KEY所对应的链表
    2、如果HASHCODE相等,判断EQUALS,如果相同,则判断两个对象相同,丢弃掉(就是放不进去)
    3、如果HASHCODE相同,EQUALS不同,那么把这个对象放在这个HASHCODE为KEY锁对应的链表的最后一位
      

  7.   


    set里面的对象都是引用,所以不存在一个引用了对象而另外一个不能引用的情况,
    而且只有object中的hashcode值才和地址对应,
    其他类中一般你都重写了hashcode。和对象的内存地址是无关
      

  8.   

    set1是一堆桶,set2又是一堆桶。两个是独立的这不就好理解了。
      

  9.   

    而且你说的是hashset如果是treeset就要看compareTo方法了。。