JavaSE进阶
11.5 Set接口
- Set接口是Collection的子接口,set接口没有提供额外的方法。
- Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
- Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法。因此存放到Set集合中的元素一定要注意equals方法的重写。
Set的常用实现类有:HashSet、TreeSet、LinkedHashSet。
11.5.1 HashSet
1、概述
- HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。
- HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能。
- HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。
- 当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值,通过某种散列函数决定该对象在 HashSet 中的存储位置。(这个散列函数会与底层数组的长度相计算得到在数组中的下标,并且这种散列函数计算还尽可能保证能均匀存储元素,越是散列分布,该散列函数设计的越好)
- 如果两个元素的hashCode()值相等,会再继续调用equals方法,如果equals方法结果为true,添加失败,如果为false,那么会保存该元素,但是该数组的位置已经有元素了,那么会通过链表的方式继续链接。
- HashSet 具有以下特点:
- 不能保证元素的排列顺序
- HashSet 不是线程安全的
- 集合元素可以有一个是 null
-
底层也是数组,初始容量为16,当如果使用率超过0.75,(16*0.75=12)就会扩大容量为原来的2倍。(16扩容为32,依次为64,128....等)
结论:存放到Set集合中的元素一定要注意equals和hashcode方法的重写。
2、hashCode和equals方法
重写equals()方法的原则:
- 对称性:如果equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。
- 自反性:equals(x)必须返回是“true”。
- 类推性:如果equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。
- 一致性:如果equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。
- 任何情况下,equals(null),永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”。
重写 hashCode() 方法的基本原则
- 在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值
- 当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等
- 对象中用作 equals() 方法比较的属性Field,都应该用来计算 hashCode 值