java.util.Set 接口和java.util.List 接口一样,同样继承自Collection 接口,
它与Collection 接口中的方法基本一致,并没有对Collection 接口进行功能上的扩充。
与List 接口不同的是, Set 接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
Set 接口常用子类:
HashSet集合
LinkedHashSet集合
Set 集合的特点:元素存取无序,无索引,不可重复
HashSet集合:
HashSet<String> hs = new HashSet<>();
hs.add("abc");
hs.add("bca");
hs.add("cba");
System.out.println(hs); //输出:[bca, abc, cba]
可从以上代码看出,HashSet集合元素存取无序
HashSet集合底层是数组与链表加红黑树实现
Set集合存取无序原理:
当元素存入集合中时,便会自动创建一个16位的数组结构
然后根据存入元素的hashCode值%16判断元素存放在数组的哪一个位置
若欲存放的数组位置已有元素,则会判断该元素与已有元素的地址值是否相同
若地址值不同,则会通过equals()方法判断元素内容是否相同
若以上判断条件都不相同,则会在该数组位置上延伸一条链表结构,用来存放hashCode%16值相同,可是内容不同的元素
Set集合存放自定义对象:
创建一个自定义类将存放在Set集合上时,集合也会默认计算元素hashCode值
哈希值就是一个十进制的整数,每一个对象都有对应的哈希值
而自定义对象没有重写hashCode()方法前就是继承Object类的hashCode()方法 (也就是计算对象的地址值)
自定义对象没有重写equals()方法前也是继承Object类的equals()方法 (还是计算对象的地址值)
则我们要重写自定义对象的hashCode(),equals()方法
一般开发工具都能使用generate自动生成:
private String name;
private int age;
private double price;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Double.compare(student.price, price) == 0 &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, price);
}
重写了euquals()方法和hashCode()方法后,就可以真正根据自定义对象的成员变量是否相同判断是否存入Set集合
HashSet<Student> hs = new HashSet();
Student s1 = new Student("1号同学", 22, 33.22);
Student s2 = new Student("1号同学", 22, 33.22);
Student s3 = new Student("2号同学", 23, 42.52);
Student s4 = new Student("3号同学", 20, 74.32);
Collections.addAll(hs, s1, s2, s3, s4);
System.out.println(hs);
//输出:
//[Student{name='2号同学', age=23, price=42.52},
//Student{name='3号同学', age=20, price=74.32},
//Student{name='1号同学', age=22, price=33.22}]
上图存入两个相同的s1,s2对象,可是集合中只会保存一个
增强for遍历Set集合:
Set集合没有索引没有存取顺序,则只能使用增强for和Iterator作遍历
具体使用方法见https://blog.csdn.net/weixin_42022555/article/details/81481889
HashSet<String> hs = new HashSet<>();
Collections.addAll(hs, "abcd", "bcad", "cbda", "dabc");
for (String str : hs) {
String s = str;
System.out.println(s); //输出:dabc cbda bcad abcd
}
Iterator迭代器遍历Set集合:
具体使用方法见https://blog.csdn.net/weixin_42022555/article/details/81481889
HashSet<String> hs = new HashSet<>();
Collections.addAll(hs, "abcd", "bcad", "cbda", "dabc");
Iterator<String> it = hs.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str); //输出:dabc cbda bcad abcd
}