HashSet添加元素是怎么判断对象是否重复的?
个人学习笔记,仅供参考,如有错误,望指正学习交流
说到hashset可以看到hash而想到哈希函数,通过一个函数将对象的属性字段转算出一列整数(散列码),而这个散列码便作为存储地址,这样可以极大提高查找的效率。不过再优秀的hash函数也会出现两个不同对象计算出相同散列码的情况。那么,hashset存储两个相同对象的时候到底发生了什么?
hashset的存储结构是数组链表,关键在于对象类是否重写了hashcode和equals方法。
1.第一,任何类都继承了Object类的hashcode()方法,如果未重写hashcode,hashset会使用默认hashcode转化对象属性字段为散列码。
2.第二,当得到散列码确定插入的位置后,接下来hashset会调用 要添加对象的equals()方法 与已经在该位置上的所有对象进行比较,如果有一个为true,则不插入,如果为false,则插入。
注意,是调用的插入对象的equals方法,不是已经在hashset中的对象。
3.看具体例子:
Set set = new HashSet();
set.add("spring");
set.add("Mybatis");
set.add("SpringMVC");
set.add("spring");//被拒绝添加
System.out.println(set);//输出结构与存入顺序无关 [spring, SpringMVC, Mybatis]
String string = "spring";
set.add(string);
System.out.println(set);/输出/[spring, SpringMVC, Mybatis]
输出
[spring, SpringMVC, Mybatis]
可以看到,插入两个spring,却只保存一个spring。
放入new的String
string = new String("spring");
String string2 = new String("spring");
set.add(string);
set.add(string2);
输出
[spring, SpringMVC, Mybatis]
两个新对象且同为spring为何添加不进去?
首先,String重写了hashcode方法,是根据字符内容得出的,所以转算出的散列码是一致的,将在hashset的同一位置插入,然后调用添加对象的equals方法,因为String的equals重写了,所以比较值为true,hashset不会添加。
总结:影响hashset插入的关键是看俩对象的hashcode与equals的重写。其实也可重写String的hashcode方法而不重写equals方法,这样也可以在hashset的不同下标位置插入一样的对象。所以使用hashset存储对象时,尽量满足equals满足为true的情况下hashcode散列码一致,equals不一致的情况下的hashcode散列码也不一致。减少冲突的发生。
个人学习笔记,仅供参考,如有错误,望指正学习交流