HashSet: 底层哈希表结构(数组+链表+红黑树),由哈希表保证元素唯一,底层是HashMap实现
哈希表的原理: 哈希表底层是数组+链表+红黑树,依赖于hashCode和equals方法
数组存储元素哈希值, 哈希值相同的存储在链表中,链表节点超过8个,链表换成红黑树,因为红黑树效率高
1.调用元素的hashCode()方法,便利数组,有没有这个哈希值,没有就直接存储
2.数组中已经有哈希值相同的,那么就调用元素的equals()方法,和哈希值相同的元素进行一一比较
3.equals()方法比较,有相等的就不存储,没有就存储
//Student类中只重写了HashCode()方法,equals和toString都没有重写
HashSet<Student> set = new HashSet<>();
Student s1 = new Student("aaa", 18);
set.add(s1);
Student s2=new Student("aaa", 18);
set.add(s2);
System.out.println("s1:"+s1);//s1:day3.Student@2d93b2
System.out.println("s2:"+s2);//s2:day3.Student@2d93b2
System.out.println(s1==s2);//false
System.out.println(s1.equals(s2));//false
- s1和s2的哈希值是一样的,因为重写了HashCode方法
- s1和s2的打印结果为什么是一样的?难道地址值一样?明明是两个对象, 这是因为打印操作调用的是Object类中的toString方法,该方法的返回值是 包名.类名@哈希值的16进制 , 哈希值一样打印的结果当然一样
- 也就是说,打印的对象值,在这里不是对象的真是地址值,所以s1.equals(s2) 和s1==s2返回的都是false,因为他们真是地址不一样.