Java如何设计自定义排序器

在使用Java无序集合时,经常需要对集合进行排序,此时需要我们自己去实现排序逻辑。接下来就以TreeSet为例来看看如何对集合进行排序。

TreeSet对元素排序有两种方式:

  • 第一种:复写Comparable接口的compareTo方法。
  • 第二种:采用自定义Comparator比较器

场景:对象Person包含姓名name和年龄age两个属性,按照年龄进行升序排序,如果年龄一致,则按照姓名升序排序。

一、复写Comparable接口的compareTo方法

让元素自身具备比较功能,元素就需要实现comparable接口,覆盖compareTo方法。

代码如下:

class Person implements Comparable{

    private String name;
    private int age;

    // 重写toString()方法,输出对象时输出格式为:name:age
    @Override
    public String toString() {
        return name+ ":" + 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;
    }

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

    @Override
    public int compareTo(Object o) {
        Person p = (Person) o;

        // 根据年龄升序排序
      int temp = this.age - p.age;
      return temp == 0 ? this.name.compareTo(p.name):temp;
    }
}

测试:

public class TreeSetDemo {
    public static void main(String[] args) {
        TreeSet<Person> ts = new TreeSet();
        ts.add(new Person("zhangsan", 20));
        ts.add(new Person("lisi", 20));
        ts.add(new Person("wangwu", 21));
        ts.add(new Person("zhouqi", 29));
        ts.add(new Person("zhaoliu", 28));

        for (Person person : ts) {
            System.out.println(person);
        }
    }
}

结果输出:

lisi:20
zhangsan:20
wangwu:21
zhaoliu:28
zhouqi:29

但是如果不要按照对象中具备的自然顺序进行排序,即对象中不具备自然顺序该如何处理呢?就需要采用下面的第二种方式。

 二、采用自定义Comparator比较器

让集合自身具备比较功能,即在集合对象创建时,由此想到TreeSet的构造方法: new TreeSet(Comparator<? super E> comparator)。为此需要定义一个类实现Comparator接口,覆盖compare方法,将该类对象作为参数传递给TreeSet集合的构造函数。

代码如下:

PersonNoComparator类不用复写Comparable接口的compareTo方法。

class PersonNoComparator {

    private String name;
    private int age;

    @Override
    public String toString() {
        return name+":" + 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;
    }

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

设计自定义排序器,并复写compare方法。

class ComparatorByAge implements Comparator {

    // 根据年龄升序排序
    @Override
    public int compare(Object o1, Object o2) {
        Person p1 = (Person) o1;
        Person p2 = (Person) o2;

        int tmp = p1.getAge() - p2.getAge();
        return tmp == 0 ? p1.getName().compareTo(p2.getName()) : tmp;
    }
}

测试:

与第一种方式测试不同的地方是,在构造TreeSet方法时直接按照ComparatorByAge排序器排序。

public class TreeSetDemo {
    public static void main(String[] args) {
        ts = new TreeSet(new ComparatorByAge());
        ts.add(new Person("zhangsan", 20));
        ts.add(new Person("lisi", 20));
        ts.add(new Person("wangwu", 21));
        ts.add(new Person("zhouqi", 29));
        ts.add(new Person("zhaoliu", 28));

        for (Person person : ts) {
            System.out.println(person);
        }
    }
}

结果输出:

lisi:20
zhangsan:20
wangwu:21
zhaoliu:28
zhouqi:29
可以发现,两种方式实现的排序结果是一致的。
 
【参考资料】
posted @ 2020-05-27 18:47  笨小康u  阅读(989)  评论(0编辑  收藏  举报