Javaでリストをソートする3つの方法

一部の特殊なシナリオでは、Java プログラムで List コレクションを並べ替える必要があります。たとえば、すべてのユーザーのリストはサードパーティのインターフェイスから取得されますが、リストはデフォルトで小さいユーザーから大きいユーザーまでのユーザー番号によって並べ替えられており、システムはユーザーの年齢に応じて最年長から若年へと並べ替える必要があります。今度は、リストを並べ替える必要があります。コレクションはカスタムの並べ替え操作を実行します。

リストの並べ替えには 3 つの一般的な方法があります。

  1. 並べ替えには Comparable を使用します。

  2. 並べ替えには Comparator を使用します。

  3. JDK 8以上の環境であればStreamを使ってソートすることも可能です。

さまざまな並べ替えメソッドの具体的な実装を見てみましょう。

1. 比較ソートを使用する

この記事で設計されたシナリオによれば、ユーザーのリストを含む List コレクションを作成し、ユーザーを年齢に応じて最年長から最年少まで並べ替える必要があります。具体的な実装コードは次のとおりです。

public class ListSortExample {
    public static void main(String[] args) {
        // 创建并初始化 List
        List<Person> list = new ArrayList<Person>() {
    
    {
            add(new Person(1, 30, "北京"));
            add(new Person(2, 20, "西安"));
            add(new Person(3, 40, "上海"));
        }};
        // 使用 Comparable 自定的规则进行排序
        Collections.sort(list);
        // 打印 list 集合
        list.forEach(p -> {
            System.out.println(p);
        });
    }
}
 
//  以下 set/get/toString 使用的是 lombok 的注解
@Getter
@Setter
@ToString
class Person implements Comparable<Person> {
    private int id;
    private int age;
    private String name;
 
    public Person(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
 
    @Override
    public int compareTo(Person p) {
        return p.getAge() - this.getAge();
    }
}

上記のコードの実行結果を次の図に示します。3023eecca875abd74e96bc3980d3bad1.pngこのメソッドのコア コードは次のとおりです。8c1f1251d06adb3863e53283b4e920e6.png

2. コンパレータを使用して並べ替える

Comparable はクラス内の比較メソッドであり、Comparator はsortクラスの外側の比較メソッドです。Comparator を使用するには、元の Person クラスを変更する必要はなく、Person クラスの Comparator を拡張するだけで済みます。Comparator を実装するには、次の 2 つの方法があります。

  • 新しい Comparator コンパレータを作成します。

  • Comparator 匿名クラス コンパレータを使用します。

このうち 2 番目の実装方法の方が簡潔なので、次の具体的なコードを通して 2 つの実装方法の違いを観察してみましょう。

2.1 新しいコンパレータの作成 コンパレータ

public class ListSortExample2 {
    public static void main(String[] args) {
        // 创建并初始化 List
        List<Person> list = new ArrayList<Person>() {
    
    {
            add(new Person(1, 30, "北京"));
            add(new Person(2, 20, "西安"));
            add(new Person(3, 40, "上海"));
        }};
        // 使用 Comparator 比较器排序
        Collections.sort(list, new PersonComparator());
        // 打印 list 集合
        list.forEach(p -> {
            System.out.println(p);
        });
    }
}
/**
 * 新建 Person 比较器
 */
class PersonComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p2.getAge() - p1.getAge();
    }
}
@Getter
@Setter
@ToString
class Person {
    private int id;
    private int age;
    private String name;
 
    public Person(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
}

上記のコードの実行結果を次の図に示します。0dff4317d7fb611999d96c0b026c15a8.pngこのメソッドのコア実装コードは次のとおりです。2b8ebcdaf8be8648aaf7b8ee60c3fc09.png

2.2 匿名クラスの比較子

コンパレータ Comparator は、より簡潔な匿名クラスを使用して並べ替え機能を実装できます。具体的な実装コードは次のとおりです。

public class ListSortExample2 {
    public static void main(String[] args) {
        // 创建并初始化 List
        List<Person> list = new ArrayList<Person>() {
    
    {
            add(new Person(1, 30, "北京"));
            add(new Person(2, 20, "西安"));
            add(new Person(3, 40, "上海"));
        }};
        // 使用匿名比较器排序
        Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                return p2.getAge() - p1.getAge();
            }
        });
        // 打印 list 集合
        list.forEach(p -> {
            System.out.println(p);
        });
    }
}
@Getter
@Setter
@ToString
class Person {
    private int id;
    private int age;
    private String name;
    public Person(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
}

上記のコードの実行結果を次の図に示します。d6953c62018302d7cb813e44d2ede799.png

3. ストリームを使用して並べ替える

JDK 8 以降では、より単純なメソッド Stream を使用して並べ替え関数を実装できます。実装に必要なコードは 1 行だけです。具体的な実装は次のとおりです。

public class ListSortExample3 {
    public static void main(String[] args) {
        // 创建并初始化 List
        List<Person> list = new ArrayList<Person>() {
    
    {
            add(new Person(1, 30, "北京"));
            add(new Person(2, 20, "西安"));
            add(new Person(3, 40, "上海"));
        }};
        // 使用 Stream 排序
        list = list.stream().sorted(Comparator.comparing(Person::getAge).reversed())
                .collect(Collectors.toList());
        // 打印 list 集合
        list.forEach(p -> {
            System.out.println(p);
        });
    }
    @Getter
    @Setter
    @ToString
    static class Person {
        private int id;
        private int age;
        private String name;
        public Person(int id, int age, String name) {
            this.id = id;
            this.age = age;
            this.name = name;
        }
    }
}

このうちreversed()は逆順を意味し、このメソッドを使用しない場合は正順となります。

上記のコードの実行結果を次の図に示します。fff8476ab84ec35a8f71ca1950ed026b.png

拡張子: 並べ替えフィールドが null です

Stream を使用してソートする場合、ソートされたフィールドに null 値があった場合、例外が発生します。具体例は次のとおりです。

public class ListSortExample4 {
    public static void main(String[] args) {
        // 创建并初始化 List
        List<Person> list = new ArrayList<Person>() {
    
    {
            add(new Person(30, "北京"));
            add(new Person(10, "西安"));
            add(new Person(40, "上海"));
            add(new Person(null, "上海")); // 年龄为 null 值
        }};
        // 按照[年龄]正序,但年龄中有一个 null 值
        list = list.stream().sorted(Comparator.comparing(Person::getAge))
                .collect(Collectors.toList());
        // 打印 list 集合
        list.forEach(p -> {
            System.out.println(p);
        });
    }
}
@Getter
@Setter
@ToString
class Person {
    private Integer age;
    private String name;
 
    public Person(Integer age, String name) {
        this.age = age;
        this.name = name;
    }
}

上記のコードの実行結果を次の図に示します。7ff5bede3329c7cca75e29a0277c6bdd.png上記の問題を解決するには、次のコードに示すように、2 番目のパラメーターを Comparator.comparing: Comparator.nullsXXX に渡す必要があります。

public class ListSortExample4 {
    public static void main(String[] args) {
        // 创建并初始化 List
        List<Person> list = new ArrayList<Person>() {
    
    {
            add(new Person(30, "北京"));
            add(new Person(10, "西安"));
            add(new Person(40, "上海"));
            add(new Person(null, "上海"));
        }};
        // 按照[年龄]正序,但年龄中有一个 null 值
        list = list.stream().sorted(Comparator.comparing(Person::getAge,
                Comparator.nullsFirst(Integer::compareTo)))
                .collect(Collectors.toList());
        // 打印 list 集合
        list.forEach(p -> {
            System.out.println(p);
        });
    }
}
@Getter
@Setter
@ToString
class Person {
    private Integer age;
    private String name;
 
    public Person(Integer age, String name) {
        this.age = age;
        this.name = name;
    }
}

Comparator.nullsFirst は、コレクションの先頭の並べ替えフィールドに null 値を配置することを意味します。null 値をコレクションの最後に配置したい場合は、Comparator.nullsLast を使用できます。

上記のコードの実行結果を次の図に示します。2abf8bb252a36cc579a3e84a01f736c4.png

要約する

この記事では、3 つのリストの並べ替えメソッドを紹介します。最初の 2 つのメソッドは、コンパレータ Comparator に 2 つの実装がある JDK 8 より前のバージョンでよく使用されます。JDK 8 以降のバージョンでは、Comparator.comparing を使用して null 値の場合の並べ替えを実装できます。並べ替えフィールドに表示される場合があります。並べ替えには Comparator.nullsXXX を使用してください (そうしないとエラーが報告されます)

おすすめ

転載: blog.csdn.net/qq_43985303/article/details/130862623