0
点赞
收藏
分享

微信扫一扫

第三次学JAVA再学不好就吃翔(part90)--TreeSet

学习笔记,仅供参考,有错必纠


文章目录

  • ​​TreeSet​​
  • ​​TreeSet存储自定义对象​​
  • ​​Comparable接口​​
  • ​​定义Dog类实现Comparable接口​​
  • ​​比较器​​
  • ​​Comparator接口的方法​​
  • ​​实现Comparator方法的案例​​
  • ​​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的规则进行比较

举报

相关推荐

0 条评论