Set是一个不包含重复元素的 collection。
Set有三个重要的实现类:HashSet,LinkedHashSet,TreeSet,下面讲解这三个实现类。
一:HashSet底层是哈希表构成,它不保证set的迭代顺序,特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
下面用代码演示为什么HashSet不保证set的迭代顺序:
import java.util.HashSet;
public class HashSetDemo {
public static void main(String[] args) {
HashSet<Integer> hashSet=new HashSet<>();
//放三个Integer对象
hashSet.add(23);
hashSet.add(324);
hashSet.add(456);
//遍历输出
for(Integer ele:hashSet){
System.out.println(ele);
}
}
}
它的输出结果是:
HashSet有两种遍历方法:
import java.util.HashSet;
import java.util.Iterator;
public class HashSetDemo {
public static void main(String[] args) {
HashSet<Integer> hashSet=new HashSet<>();
hashSet.add(23);
hashSet.add(324);
hashSet.add(456);
hashSet.add(678);
hashSet.add(12);
//使用增强for循环遍历
for(Integer ele:hashSet){
System.out.println(ele);
}
System.out.println("-------------------------");
//使用 Iterable接口提供的迭代器进行遍历
Iterator ite=hashSet.iterator();
while(ite.hasNext()){
System.out.println(ite.next());
}
}
}
二:LinkedHashSet是具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。
此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序不 受在 set 中重新插入的 元素的影响。
此类提供所有可选的 Set 操作,并且允许 null 元素。
由于增加了维护链接列表的开支,其性能很可能会比 HashSet 稍逊一筹,不过,这一点例外:LinkedHashSet 迭代所需时间与 set 的大小 成正比,而与容量无关。HashSet 迭代很可能支出较大,因为它所需迭代时间与其容量 成正比。
LinkedHashSet有两种遍历方法:
import java.util.Iterator;
import java.util.LinkedHashSet;
public class LinkerHashSetDemo {
public static void main(String[] args) {
LinkedHashSet<Integer> lhS=new LinkedHashSet<>();
lhS.add(123);
lhS.add(423);
lhS.add(543);
lhS.add(321);
lhS.add(654);
//使用增强for循环进行遍历
for (Integer ele:lhS){
System.out.println(ele);
}
System.out.println("--------------------");
//使用Iterable接口提供的迭代器
Iterator ite=lhS.iterator();
while(ite.hasNext()){
System.out.println(ite.next());
}
}
}
三:TreeSet使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的Comparator 进行排序,具体取决于使用的构造方法。
注意:如果是元素为自定义对象,一定要实现Comparable接口,否则无法进行排序。
下面我先定义一个对象为Integer对象的TreeSet,演示一下自然排序:
import java.util.TreeSet;
public class TreeSetDemo3 {
public static void main(String[] args) {
TreeSet<Integer> treeSet=new TreeSet<>();
treeSet.add(64);
treeSet.add(15);
treeSet.add(236);
treeSet.add(184);
treeSet.add(345);
for(Integer ele:treeSet){
System.out.println(ele);
}
}
}
输出结果是:
下面我定义一个存储自定义对象的TreeSet:
先是自定义对象类:
public class Student {
private String name;
private int age;
public Student(String 楚留香, int i, int i1, int i2) {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class TreeSetDemo2 {
public static void main(String[] args) {
//这里我使用匿名内部类传进去一个比较器,该比较器使用总分进行排序
TreeSet<StudentScore> stu=new TreeSet<>(new Comparator<StudentScore>() {
@Override
public int compare(StudentScore a, StudentScore b) {
int anum=a.getCscore()+a.getEscore()+a.getMscore();
int bnum=b.getCscore()+b.getEscore()+b.getMscore();
int num=(anum-bnum)==0?a.getName().compareTo(b.getName()):(anum-bnum);
return -num;
}
});
StudentScore stu1=new StudentScore("楚留香",98,95,97);
StudentScore stu2=new StudentScore("陆小凤",95,96,94);
StudentScore stu3=new StudentScore("李寻欢",93,91,93);
StudentScore stu4=new StudentScore("小鱼儿",99,97,89);
stu.add(stu1);
stu.add(stu2);
stu.add(stu3);
stu.add(stu4);
for(StudentScore ele:stu){
System.out.println(ele);
}
}
}
运行结果是:
这个例子我是使用匿名内部类传进去一个比较器,大家也可以在Student类中实现Comparable接口,然后重写compareTo方法,这两个方法都可以。