1.Set集合的特点
(1)唯一性:不可添加重复元素
(2)无序性:输出元素的顺序跟添加元素的顺序不一致,且没有元素下标。
(3)可哈希性:Set中的元素必须是可哈希的,即元素必须有一个明确的哈希值。如果一个元素没有哈希值,那么它就不能被用作Set的元素。
(4)内部实现:Set内部通常基于哈希表或平衡树等数据结构实现,这提供了快速插入、删除和查找的操作。由于内部实现采用哈希表或树形结构,查找某个元素的时间复杂度为O(1)或O(log n)。
(5)Set集合由于没有继承ListIterator,所以无法调用其方法,但是能够调用Iterator。
2.Set集合的遍历方式
(1)for遍历:
由于for循环遍历集合需要依靠下标遍历集合元素,所以此遍历方式无法实现对Set集合的遍历。
(2)foreach遍历:
代码如下:
Set<String> set=new Set<>();
set.add(new Student("z");
set.add(new Student("x"));
set.add(new Student("a"));
for (Student s: set) {
System.out.println(s);
}
(3)迭代器遍历:
前面说到Set集合无法调用Listiterator,所以此处一定是调用iterator。
代码如下:
Iterator<Student> it = set.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
3.Set集合存在的问题
(1) Set集合的特点之一是唯一性,但我们在开发软件时大多都是将对象添加到集合中,那么这时添加两个属性值完全相同的对象,唯一性可能就不成立啦,这是为什么呢?问题就出在hashCode()和equals(),这两个方法,一个比较哈希码,一个比较字符,并且,比较顺序是先比较哈希码,如果相同,再用equals()比较;如果哈希码不同,它就不会用equals()比较啦。
这时我们需要去重写equals(),这两个方法。
修改成这样:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (sname.equals(student.sname)){
//为相同,将相同的那一个元素剔除
return true;
}else{
//为不相同,保留元素
return false;
}
}
(2)这个时候有人还问:“我要是传入的两相同姓名,但是年龄或者成绩不同的对象,那该怎么办啊?”。这个时候就要从hashCode()下手啦,上面说到,比较顺序是先比较哈希码,如果相,再用equals()比较;如果哈希码不同,它就不会用equals()比较啦。
那么,这种情况下,主要导致问题的是传入对象的成绩或者年龄属性的哈希码,因为它发现两个对象的成绩或者年龄属性哈希码的值不同啦,它就不会再去用equals(),进而导致了相同姓名,不同年龄或成绩的对象添加到了Set集合中,所以解决方式是,我们干脆直接不让它去比较成绩或者年龄的哈希码。
如下:
public int hashCode() {
int result = sid != null ? sid.hashCode() : 0;
result = 31 * result + (sname != null ? sname.hashCode() : 0);
return result;
}