Set集合
Set集合概述
- Set集合类似于一个罐子,他只管把对象放进罐子中,而不管放入的次序
- Set集合与Collection集合基本相同,没有提供任何额外的方法
- Set集合不允许添加重复元素,若试图添加两个相同元素进入同一个Set集合中,则添加失败,add()方法返回false, 且新元素不会被加入
Set集合的实现类——HashSet类
- HashSet是Set接口的典型实现
- HashSet按Hash算法来存储集合中的元素,具有很好的存取和查找性能
- HashSet的特点:
- 不能保证元素的排列顺序
- HashSet不是同步的,若多个线程同时访问同一个HashSet,假设两个或以上线程同时修改HashSet集合时,必须通过代码来保证其同步。
- 集合元素可以是null
- HashSet集合判断两个元素是否相等是根据equals()方法的返回值和hashCode()的返回值来判断的,当equals()方法的返回值为true且hashCode()返回值相等时会认为两个元素相等
HashSet集合通过hashCode()方法的返回值来决定元素的位置,若两个元素通过equals()方法返回true,但是hashCode()方法返回值不同,HashSet()集合会将这两个元素存储到不同的位置
若需要将某个类的对象保存到HashSet集合时,建议重写equals()方法的同时也重写hashCode()方法,并且应尽量保证equals()方法返回true时它们的hashCode()方法返回值也相等
HashSet中每个能存储元素的“槽位“”称为“桶”, 如果有多个hashCode值相同,但equals()却返回false,就需要在一个“桶”中放多个元素,这样会导致性能下降。
- 重写hashCode()方法的基本规则:
- 在程序运行过程中,同一对象多次调用hashCode()方法应返回相同的值
- 当两个对象equals()方法返回true时两个hashCode值应相等
- 对象中用作equals()方法比较标准的实例变量,都应用于计算hashCode值
- 如果像HashSet集合中添加一个可变对象后,然后修改了可变对象的引用值(实例对象),则可能导致它与集合中另一个元素相等,这就导致了HashSet集合中有两个相同的元素,导致性能下降。
import java.util.HashSet;
import java.util.Iterator;
import java.util.Objects;
class R {
int count;
public R(int count) {
this.count = count;
}
@Override
public String toString() {
return "R[count:" + count + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
R r = (R) o;
return count == r.count;
}
@Override
public int hashCode() {
return this.count;
}
}
public class HashSetTest {
public static void main(String[] args) {
HashSet hs = new HashSet();
hs.add(new R(5));
hs.add(new R(3));
hs.add(new R(-2));
hs.add(new R(20));
System.out.print