一、问题分析

对于TreeSet类,假如添加对象的类中不实现Comparable接口重写compareTo方法或者TreesSet创建对象未传入自定义的比较类的话,那么运行时将会报错!
​​​Exception in thread "main" java.lang.ClassCastException: cn.com.clearlight.setframe.set.bean.Student cannot be cast to java.lang.Comparable​

下面的类还未实现比较器的接口,运行将会报错.

Student类

package cn.com.clearlight.setframe.set.bean;

import java.util.Objects;

public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public void setName(String name) {
this.name = name;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}
}

TreeSetForCompare类

package cn.com.clearlight.setframe.set;

import cn.com.clearlight.setframe.set.bean.Student;
import cn.com.clearlight.setframe.set.comparator.ComparatorByName;

import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetForCompare {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<>();
ts.add(new Student("ac", 1));
ts.add(new Student("a", 1));
ts.add(new Student("d", 4));
ts.add(new Student("d", 4));
ts.add(new Student("ab", 3));
ts.add(new Student("ab", 1));

Iterator<Student> iterator = ts.iterator();

for (Student s : ts) {
System.out.println(s.getName()+":"+s.getAge());
}
}
}

TreeSet作为一种Set,它不允许出现重复元素。TreeSet是用compareTo()来判断重复元素的,而非equals().Student类中不重写equals和hashCode方法,对于添加的元素是否有重复的最终结果并没有影响!因此TreeSet在比较的时候,根本没有调用equals方法!


二、完成比较有两种方法可以实现



1、实现Comparable接口,重写compareTo方法

在自定义的类中实现Comparable接口,重写compareTo()方法即可.

上面Student类需要添加的东西

public class Student implements Comparable<Student> {
@Override
public int compareTo(Student o) {
// 先根据年龄来排序,若年龄相同,则根据String类型中实现的compareTo方法进行排序
int temp = this.age - o.age;
return temp == 0 ? this.name.compareTo(o.name) : temp;
}
}

TreeSetForCompare类的输出结果

a:1
ab:1
ac:1
ab:3
d:4


2、写比较类实现Comparator方法

  1. 新建一个类,实现Comparator类,并重写compare(T o1, T o2)
  2. TreeSetForCompare类中在创建TreeSet对象时,传入参数对此 set 进行排序的比较器

新建的ComparatorByName类

package cn.com.clearlight.setframe.set.comparator;

import cn.com.clearlight.setframe.set.bean.Student;

import java.util.Comparator;

public class ComparatorByName implements Comparator<Student> {


@Override
public int compare(Student o1, Student o2) {
// 先根据名字来排序,若名字相同,则根据年龄的大小来排序
int temp = o1.getName().compareTo(o2.getName());
return temp==0 ? o1.getAge()-o2.getAge() : temp;
}
}

修改的TreeSetForCompare类

​TreeSet<Student> ts = new TreeSet<>(new ComparatorByName());​

TreeSetForCompare类的输出结果

a:1
ab:1
ab:3
ac:1
d:4

三、总结

对于TreeSet类添加自定义对象时,可以通过两种方法来完成比较。

你还需要知道的是,如果同时实现这两种方法的话,第二种方法的优先级高于第一种方法,
即将会按照自定义的比较器的比较方法进行比较!