TreeSet的定制排序:

这里我们举一个例子来理解TreeSet的定制排序

eg:

package 集合;

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo1 {

    public static void main(String[] args) {
        /*
        这里我们使用匿名内部类的方式创建了一个Comparator接口的实现类的对象
         */
        Comparator com = new Comparator() {
            @Override
            /* 
            这里我们可以发现我们重写这个compare()方法比较的是两个User类中的age属性
             */
            public int compare(Object o1, Object o2) {
                if(o1 instanceof User&&o2 instanceof User){
                    User u1 = (User)o1;
                    User u2 = (User)o2;
                    return Integer.compare(u1.getAge(),u2.getAge());
                }else{
                    throw new RuntimeException("输入数据与User类型不匹配");
                }
            }
        };
        /*
        这里我们调用了TreeSet类中的有参构造方法,这个时候参数为我们的Comparator接口的实现类的对象
        那么这个时候表示我们要使用定制排序的方式进行排序,这个时候也就是根据compare()方法进行判断
         */
        TreeSet t = new TreeSet(com);
        t.add(new User("Tom",12));
        t.add(new User("mark",12));
        t.add(new User("jim",13));
        t.add(new User("jack",12));
        t.add(new User("Tom",15));
        /*
        通过这里的输出我们可以发现,我们这里在t中只有"Tom",12 还有 "Tom",15 还有 "jim",13,
        这个是因为什么?
        因为我们的TreeSet中判断数据是否重复是通过比较器中的方法判断的,也即是这个时候只要我们的两个User类的对象的
        age相同,就表示这两个对象重复了,所以我们上面年龄为12岁的User对象都算是重复了
         */
        t.forEach(System.out::println);

    }
}
class User{
    private String name;
    private int age;
    public User(){

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

这里我们总结以下几点:

  1. 我们使用定制排序的前提是我们创建了一个Comparator接口的实现类的对象,并且将Comparator实现类的这个对象传入TreeSet的构造方法中
  • 这个时候我们使用TreeSet类的有参构造方法,将我们创建的Comparator接口的实现类的对象传入这个构造方法中,这个时候我们就是使用compare()方法进行排序
  1. 我们使用地址排序不是创建Comparator接口的实现类的对象就可以,我们还要将这个实现类的对象传入TreeSet的构造方法中去,这个时候创建的TreeSet才是使用默认排序方式进行的排序
  2. 我们使用TreeSet的无参构造方法创建出来的对象就是使用自然排序
  • 如果我们要使用定制排序就一定要将我们创建的Comparator接口实现类创建对象,然后将这个对象传入TreeSet类的构造方法中
  1. 我们建议使用TreeSet集合时一定要在TreeSet集合存储的元素的模板类中实现Comparable接口,并且重写这个接口中的compareTo()方法,在这个基础上我们如果要使用定制排序,这个时候如果我们的自然排序满足不了我们的这个时候的需求,这个时候我们就可以创建一个Comparator接口的实现类的对象,然后再将这个对象传入TreeSet构造方法中去实现我们的定制排序

关于TreeSet自然排序与TreeSet定制排序的总结:

在自然排序中,比较两个对象是否相同的标准为:compareTo()方法的返回值为0,为0则表示重复,而不再是使用equals()方法判断

在定制排序中,比较两个对象是否相同的标准为:Compare()方法的返回值为0.为0则表示重复,而不再是使用equals()方法判断

补充:

我们的包装类中有一个compare()静态方法

  • 这里我们以Double类中的compare()方法为例讲解
  • public static int compare(double a,double b);
  • 这个方法是一个静态方法
  • 我们使用这个方法要传入两个double型的参数,这个时候我们的compareTo()方法就会返回一个int类型的值,如果形参a>形参b,这个时候返回1,如果形参a<形参b,这个时候返回-1,如果形参a=形参b ,这个时候返回一个0
  • 这里我们只是使用Double类中的compare()方法举了一个例子,这个方法在我们的其他包装类中也有
  • 包括我们的Boolean类中也有compare()静态方法