Set接口及其实现类
概述
Set接口同List接口一样,继承自Collection接口,与Collection中方法基本一致。与List接口不同的是,Set接口中元素无序,元素不重复。
Set接口的两个实现类
HashSet集合
基于HashMap存储,HashSet根据对象的哈希值确定集合中的储存位置,因此具有良好的存取和查找性能。
HashSet代码示例如下:
HashSet<String> set = new HashSet<>();
set.add("Data_1");
set.add("Data_2");
set.add("Data_3");
set.add("Data_3");
//创建iterator对象
Iterator<String> it = set.iterator();
while (it.hasNext()){
String str = it.next();
System.out.println(str);
}
运行结果如下:
Data_3
Data_1
Data_2
从打印结果可以看出,
取出元素的顺序与添加元素的顺序不一致,说明Set接口无序。重复存入的字符串对象"Data_3"被去除了,只添加了一次。说明Set接口没有重复元素。
HashSet集合之所以能确保不出现重复元素,因为存入元素时做了很多操作,调用HashSet集合时,
- 当前存入对象的hashCode()方法获得对象的哈希值,根据对象的哈希值计算出一个存储位置。
- 如果该位置上没有元素,则直接将元素存入。如果该位置上有元素存在,则会调用equals()方法让当前存入的元素一次和该位置上的元素进行比较,如果返回false就存入集合,如果返回true说明有重复元素,舍弃该元素。
HashSet存入对象元素的注意事项
根据前面的分析不难看出,当向集合中存入元素时,为了保证HashSet正常工作,要求在存入对象时,重写Object类中的hashCode()和equals()方法。
先创建一个类,具体代码示例如下:
String id;
String name;
public Teacher(){}
public Teacher(String id,String name){
this.id = id;
this.name = name;
}
public String toString(){
return id + ":" + name;
}
测试类代码如下:
public class Test {
public static void main(String[] args){
HashSet hs = new HashSet<>();
Teacher t1 = new Teacher("1", "Jack");
Teacher t2 = new Teacher("1", "Jack");
Teacher t3 = new Teacher("2", "Rose");
hs.add(t1);
hs.add(t2);
hs.add(t3);
System.out.println(hs);
}
}
运行结果如下所示:
[1:Jack, 2:Rose, 1:Jack]
由结果我们看出HashSet类型的数据中出现了两个相同的元素。之所以没去掉这样的重复元素,
因为定义Student类时没有重写hashCode()和equals()方法。
下面我们在Teacher类中重写这hashCode()和equals()方法:
public class Teacher {
String id;
String name;
public Teacher(){}
public Teacher(String id,String name){
this.id = id;
this.name = name;
}
//重写toString()方法
public String toString(){
return id + ":" + name;
}
//重写hashCode()方法
public int hashCode(){
return id.hashCode();
}
//重写equals方法
public boolean equals(Object obj){
//同一个对象返回true
if (this == obj)
return true;
//对象为空返回false
if (obj == null)
return false;
//如果obj为Teacher类型
if (obj instanceof Teacher){
//判断值是否相同
Teacher t = (Teacher) obj;
if (this.id.equals(t.id) && this.name.equals(t.name)){
return true;
}
}
return true;
}
}
由上述代码看出,在hashCode()方法中返回id属性的哈希值,在equals()方法中比较对象的id属性是否相等,并返回结果。
TreeSet集合
基于TreeMap实现,有序的、不含有重复元素的集合。
代码演示如下:
TreeSet<String> ts = new TreeSet<>();
ts.add("B");
ts.add("D");
ts.add("A");
ts.add("C");
System.out.println(ts);
运行结果如下:
[A, B, C, D]
由结果可以看出,TreeSet并不是按照存入的顺序存储,也不是无序存储,而是根据字母顺序进行排序的存储。
使用treeSet存储对象类型的元素
先创建对象,代码如下:
public class Teacher {
int id;
String name;
public Teacher(){}
public Teacher(int id,String name){
this.id = id;
this.name = name;
}
//重写toString()方法
public String toString(){
return id + ":" + name;
}
}
程序入口代码如下:
public static void main(String[] args){
TreeSet<Teacher> ts = new TreeSet<>();
Teacher t1 = new Teacher("1", "Jack");
Teacher t2 = new Teacher("2", "Rose");
Teacher t3 = new Teacher("3", "Sam");
ts.add(t1);
ts.add(t2);
ts.add(t3);
System.out.println(ts);
}
运行结果如下:

之所以报出这样的错误,
因为JDK不知到怎么去对Teacher对象排序,Teacher类必须实现排序接口Comparable才能作为TreeSet的元素存储。
浙公网安备 33010602011771号