一、Set接口简介
Set接口继承自Collection接口,与Collection接口的方法基本一致,其中元素无序且不可重复。主要有HashSet和TreeSet两个实现类。
二、HashSet集合
HashSet是Set接口的一个实现类,根据对象的散列值来确定元素在集合中的存储位置,具有良好的存取和查找性能。
创建HashSet集合:HashSet set = new HashSet();
向该Set集合中添加元素:set.add(“元素内容”);
举个例子:
import java.util.HashSet;
import java.util.Iterator;
public class egforHashSet {
public static void main(String[] args){
HashSet set = new HashSet(); //创建HashSet集合
set.add("张三"); //向该集合中添加字符串
set.add("李四");
set.add("王五");
set.add("李四");
System.out.println(set); //直接输出集合
//使用Iterator迭代器输出集合
Iterator it = set.iterator(); //获取迭代器对象
while(it.hasNext()){ //判断集合中是否还有元素
Object obj = it.next(); //如果有元素,就通过迭代器的next()方法获取元素
System.out.println(obj);
}
}
}
HashSet为什么能确保不出现重复的元素?
因为当调用HashSet集合的add()方法存入元素时,首先调用当前存入对象的hashCode()方法获取对象的散列值,然后根据对象的散列值计算出一个存储位置。如果该位置上没有元素,则直接将元素存入;如果该位置上有元素存在,则会调用equals()方法让当前存入的元素依次与该位置上的元素进行比较,如果返回的结果为false就将该元素存入集合,返回的结果为true则说明有重复元素,将该元素舍弃。
与此同时,为了保证HashSet正常工作,要求在存入自定义对象时重写Object类中的hashCode()和equals()方法,否则将无法避免重复元素的出现。
举个例子:
import java.util.HashSet;
import java.util.Objects;
class Student{
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(String id, String name) {
this.id = id;
this.name = name;
}
//重写toString方法
@Override
public String toString() {
return id + ":" + name;
}
//重写hashCode方法
@Override
public int hashCode() {
return Objects.hash(id, name);
}
//重写equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(id, student.id) && Objects.equals(name, student.name);
}
}
public class egforLinkedHashSet {
public static void main(String[] args){
HashSet hs = new HashSet();
Student stu1 = new Student("1","张三");
Student stu2 = new Student("2","李四");
Student stu3 = new Student("2","李四");
hs.add(stu1);
hs.add(stu2);
hs.add(stu3);
System.out.println(hs);
}
}
另外,HashSet集合存储的元素是无序的,如果想让元素的存取顺序一致,可以使用LinkedHashSet类,类似于LinkedList,它也使用双向链表来维护内部元素的关系。
创建LinkedHashSet集合:LinkedHashSet set = new LinkedHashSet();
向该Set集合中添加元素:set.add(“元素内容”);
举个例子:
import java.util.Iterator;
import java.util.LinkedHashSet;
public class egforLinkedHashSet {
public static void main(String[] args){
LinkedHashSet set = new LinkedHashSet(); //创建LinkedHashSet集合
set.add("张三"); //向该集合中添加字符串
set.add("李四");
set.add("王五");
set.add("李四");
System.out.println(set); //直接输出集合
//使用Iterator迭代器输出集合
Iterator it = set.iterator(); //获取迭代器对象
while(it.hasNext()){ //判断集合中是否还有元素
Object obj = it.next(); //如果有元素,就通过迭代器的next()方法获取元素
System.out.println(obj);
}
}
}
三、TreeSet集合
TreeSet同样是Set接口的一个实现类,以二叉树的方式来存储元素,它可以实现对集合中的元素进行排序。
创建TreeSet集合:TreeSet ts = new TreeSet();
向该Set集合中添加元素:ts.add(“元素”);
TreeSet集合为什么可以对元素进行排序?
1、自然排序:
元素的类可以实现Comparable接口,Comparble接口强行对实现它的每个类的对象进行整体排序,这种排序称为类的自然排序。Comoarable接口的compareTo()方法称为自然比较方法。对象必须实现Comparable接口并且重写comparableTo()方法才能实现对象元素的顺序存取。其中,当compareTo()方法返回0的时候集合中只有一个元素,当compareTo()方法返回正数时集合会正常存取,当compareTo()方法返回负数时集合会倒序存取。
举个例子:
import java.util.TreeSet;
class Student implements Comparable<Student>{
private String id;
private String name;
public Student(String id,String name) {
this.id = id;
this.name = name;
}
@Override //重写toString方法
public String toString() {
return id + ':' + name;
}
@Override //重写compareTo方法
public int compareTo(Student o) {
// return 0; //集合中只有一个元素
// return 1; //集合按照怎么存就怎么取
return -1; //集合按照存入顺序的倒序进行存储
}
}
public class eg4TreeSet {
public static void main(String[] args){
TreeSet ts = new TreeSet();
ts.add(new Student("1","张三"));
ts.add(new Student("2","李四"));
ts.add(new Student("3","王五"));
System.out.println(ts);
}
}
2、比较排序
实现Comparator接口,重写compare()方法和equals方法,不过由于所有类都默认继承Object类已经有了equals方法,所以自定义比较器类时不用重写equals方法,只需要重写conpare()方法。
举个例子:
import java.util.Comparator;
import java.util.TreeSet;
class Student {
private String id;
private String name;
public Student(String id, String name) {
this.id = id;
this.name = name;
}
@Override //重写toString方法
public String toString() {
return id + ':' + name;
}
}
public class eg4TreeSet {
public static void main(String[] args){
TreeSet ts = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return -1;
}
});
ts.add(new Student("1","张三"));
ts.add(new Student("2","李四"));
ts.add(new Student("3","王五"));
System.out.println(ts);
}
}