Set、HashSet 存放的不是元素,存的是Hash表,哈希表里存放的是哈希值。
HashSet 存储元素的顺序并不是按照存入的顺序来的(这和 List 显然不同),而是按照哈希值来存的,所以取数据也是按照哈希值取得。元素的哈希值是通过元素的 hashCode() 方法来获取的, HashSet 首先判断两个元素的哈希值,如果哈希值一样,接着会比较 equals() 方法,如果 equals() 方法结果为 true,HashSet 就视为同一个元素。如果 equals() 为false 就不是同一个元素。
哈希值不同说明两个元素不同,好理解。那哈希值相同、equals() 为false的元素怎么存储呢?
两个元素在同样的哈希值下,比较出equals的值不同,就在相同的 哈希值下顺延(可以理解成哈希值相同的元素放在一个“哈希桶”中,把它们按照羽毛球桶存放羽毛球类似的结构存放)。也就是哈希一样的列。
HashSet 通过 hashCode 值来确定元素在内存中的位置。一个 hahsCode 位置上可以存放多个元素。
Java 的集合有两类,一类是 List,还有一类是 Set。List是有序可重复,Set 无须不重复。
当我们在 set 集合中插入的时候怎么判断是否已经存在该元素呢,可通过 equals 方法。但是如果元素太多,用这样的方法就会比较慢。
于是就有人发明了 哈希算法
来提高集合中查找元素的效率。
这种方式将集合分成若干个存储区域,每个存储的对象可以计算出一个哈希码,可以将哈希码范围分组划分,每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该存储的哪个区域。
它返回的就是根据对象的内存地址换算出来的一个值。这样一来,当集合要添加新的元素时,先调用这个元素的 hashCode 方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的 equals 方法与新元素进行比较:相同的话就不存了,不相同就散列其他地址。这样一来实际调用 equals 方法的次数就大大降低了,几乎只需要一两次。