IT Notes‎ > ‎Java‎ > ‎Java Language‎ > ‎

List 中元素的排序

List 中的元素不一定都是 String, Number 这种类型的,遇到自定义的对象,需要按对象的某一个维度去排序,该如何做?这里用两种方式实现,但暂时不深究原理。个人较为推崇第二种方法,代码耦合少。
本文用到的代码存于:http://git.oschina.net/iridiumcao/iridiumonline/tree/master/hellojavase/src/main/java/info/iridiumcao/hellojavase/collection

法一 让被排序元素实现 Comparable 接口

简单地说,就是让需要排序的元素实现 Comparable 接口,元素加入到 List 后,直接调用 Collections.sort(Object) 方法即可。参考代码如下:
public class Person implements Comparable<Person> {

    private String name;
    private int age;
    private String email;

    public Person() {

    }

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

    //... 此处省略 getter 和 setter 方法,以节省篇幅。

    @Override
    public String toString() {
        return this.name + ": " + age;
    }

    @Override
    public int compareTo(Person o) {
        return this.getAge() - o.getAge();
    }

}

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Client {

    public static void main(String[] args) {
        Person p1 = new Person("Zhang San", 30, "zhangsan@hotmail.com");
        Person p2 = new Person("Li Si", 29, "lisi@gmail.com");
        Person p3 = new Person("Wang Wu", 100, "wangwu@yahoo.com");

        List<Person> list = new ArrayList<Person>();
        list.add(p1);
        list.add(p2);
        list.add(p3);

        for (Person p : list) {
            System.out.println(p);
        }

        Collections.sort(list);

        for (Person p : list) {
            System.out.println(p);
        }
    }

}

法二 单独实现 Comparator 接口

简单地说,这种方法不需要改变被排序元素的类,需要一个 Comparator 的实例,然后调用 Collections.sort(Object, Comparator) 方法。实际使用时,如果比较规则很简单,使用内部匿名类即可。这种方法可达到「非侵入式」(non-intrusive)。
public class Person {
    private String name;
    private int age;
    private String email;

    public Person() {
    }

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

    //... 此处省略 getter 和 setter 方法,以节省篇幅。

    @Override
    public String toString() {
        return this.name + ": " + age;
    }

}

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Client1 {

    public static void main(String[] args) {
        Person p1 = new Person("Zhang San", 30, "zhangsan@hotmail.com");
        Person p2 = new Person("Li Si", 29, "lisi@gmail.com");
        Person p3 = new Person("Wang Wu", 100, "wangwu@yahoo.com");

        List<Person> list = new ArrayList<Person>();
        list.add(p1);
        list.add(p2);
        list.add(p3);

        for (Person p : list) {
            System.out.println(p);
        }

        Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge();
            }

        });

        for (Person p : list) {
            System.out.println(p);
        }
    }

}
Collections.sort 方法的第二个参数是一个匿名的 Comparator 子类,这个写法,很有些 FP(函数式编程) 的味道,不过这里传入的是类。这个 Client 类还可以用 Java 8的新语法改写为:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 本例应用 Java 8 的 lambda 表达式以及 forEach 循环
 */
public class Client2 {
    public static void main(String[] args) {
        Person p1 = new Person("Zhang San", 30, "zhangsan@hotmail.com");
        Person p2 = new Person("Li Si", 29, "lisi@gmail.com");
        Person p3 = new Person("Wang Wu", 100, "wangwu@yahoo.com");

        List<Person> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);
        list.add(p3);

        list.forEach(System.out::println);

        Collections.sort(list, (o1, o2) -> {
            return o1.getAge() - o2.getAge(); // 以年龄排序
        });

        list.forEach(System.out::println);
    }
}


Comments