第三次学JAVA再学不好就吃翔(part90)--TreeSet
学习笔记,仅供参考,有错必纠
文章目录
TreeSet
该类基于TreeMap的 NavigableSet 实现,使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的Comparator进行排序,具体取决于使用的构造方法。
- 举个例子
package com.guiyang.restudy3;
import java.util.TreeSet;
public class D3TreeSet {
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<>();
ts.add(3);
ts.add(1);
ts.add(1);
ts.add(2);
ts.add(2);
ts.add(3);
ts.add(3);
System.out.println(ts);
}
}
输出:
[1, 2, 3]
TreeSet存储自定义对象
Comparable接口
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo
方法被称为它的自然比较方法。
- compareTo方法
int compareTo(T o)
比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
定义Dog类实现Comparable接口
现在,我们构造Dog类,并实现Comparable接口,并重写compareTo方法:
package com.guiyang.eclipse;
public class Dog implements Comparable<Dog>{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public Dog() {}
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 int compareTo(Dog o) {
return 0;
//return 1;
//return -1;
}
@Override
public String toString() {
return "<name:" + name + ", age:" + age + ">";
}
}
需要注意的是,当compareTo方法返回值恒为0的时候,TreeSet集合中只有一个元素,当compareTo方法返回值恒为正数(比如1)时,TreeSet集合会怎么存就怎么取,当compareTo方法返回值恒为负数时(比如-1),TreeSet集合会按照倒序存储。
我们按照age和name的大小,重写compareTo方法:
@Override
public int compareTo(Dog o) {
int num = this.age - o.age;
return num == 0 ? this.name.compareTo(o.name) : num;
//上述代码表示,年龄相同比较name,不相同则返回num
//String类已经对compareTo方法进行了重写,返回一个int值
}
现在我们用TreeSet存储自定义Dog类:
package com.guiyang.restudy3;
import java.util.Comparator;
import java.util.TreeSet;
import com.guiyang.eclipse.Dog;
public class D4TreeSetDog {
public static void main(String[] args) {
TreeSet<Dog> ts = new TreeSet<>();
ts.add(new Dog("Huang", 9));
ts.add(new Dog("Black", 10));
ts.add(new Dog("Pink", 5));
ts.add(new Dog("Green", 10));
ts.add(new Dog("Huang", 12));
System.out.println(ts);
}
}
输出:
[<name:Pink, age:5>, <name:Huang, age:9>, <name:Black, age:10>, <name:Green, age:10>, <name:Huang, age:12>]
比较器
我们看一个TreeSet的有参构造方法:
TreeSet(Comparator<? super E> comparator)
构造一个新的空TreeSet,它根据指定的比较器进行排序。
这个Comparator是一个接口,我们不能直接创建其对象,而需要先构造它的子类去实现该接口,并重写接口里的方法。
Comparator接口的方法
- compare方法
int compare(T o1, T o2)
比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。
- equals方法
boolean equals(Object obj)
指示某个其他对象是否"等于"此 Comparator,仅当指定的对象也是一个 Comparator,并且强行实施与此 Comparator 相同的排序时,此方法才返回 true。因此,comp1.equals(comp2)
意味着对于每个对象引用 o1 和 o2 而言,都存在 sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2))
实现Comparator方法的案例
package com.guiyang.restudy3;
import java.util.Comparator;
import java.util.TreeSet;
public class D4TreeSetDog {
public static void main(String[] args) {
//将字符串按照长度排序
TreeSet<String> ts = new TreeSet<>(new CompareByLen()); //Comparator c = new CompareByLen();
ts.add("aaaaaaaa");
ts.add("bbb");
ts.add("ddddd");
ts.add("aaa");
ts.add("e");
System.out.println(ts);
}
}
class CompareByLen implements Comparator<String> {
//默认继承Object类,Object类中已经重写了equels方法
@Override
public int compare(String s1, String s2) { //按照字符串的长度比较
int num = s1.length() - s2.length(); //长度为主要条件
return num == 0 ? s1.compareTo(s2) : num; //内容为次要条件
}
}
输出:
[e, aaa, bbb, ddddd, aaaaaaaa]
TreeSet原理
TreeSet是用来排序的,可以指定一个顺序, 对象存入之后会按照指定的顺序排列,这两种顺序分别为自然顺序和比较器顺序。
- 自然顺序(Comparable)
- TreeSet类的add()方法中会把存入的对象提升为Comparable类型
- 调用对象的compareTo()方法和集合中的对象比较
- 根据compareTo()方法返回的结果进行存储
- 比较器顺序(Comparator)
- 创建TreeSet的时候可以制定 一个Comparator
- 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
- add()方法内部会自动调用Comparator接口中compare()方法排序
- 调用的对象是compare方法的第一个参数,集合中已添加的对象是compare方法的第二个参数
- 两种方式的区别
- 在TreeSet构造方法中,如果什么都不传, 默认按照类中Comparable的规则进行比较(若该类没有实现Comparable类,就会报出ClassCastException错误)
- 在TreeSet构造方法中,如果传入Comparator, 就优先按照Comparator的规则进行比较
本文地址:https://blog.csdn.net/m0_37422217/article/details/107270494
上一篇: 表嫂和表哥吵架后