Java入門 / Javaの構文

【Java入門 実用編】List のソートと Comparator |  コレクションクラスの活用

2025.12.19

株式会社GSI ITエンジニア募集【成長をカタチに】

実務でJavaを利用する場合、画面表示やデータ加工のために List の要素を並び替える「ソート処理」が必要となるケースはよくあります。

ソートは単純な処理である一方、Collections.sort を使う方法から、Stream API による直感的な記述まで、用途に応じた方法が準備されているポイントでもあります。

本記事では、最初の一歩として基本となるソートの方法についてご紹介します。

◆Java入門 記事一覧はこちら

基本的なソートの方法

Javaでリストを並び替える(ソートする)基本的な方法として、レガシーなユーティリティクラスの Collections.sort メソッドを使う方法と、リストのクラス自身が持っている List.sort メソッドを使う方法があります。

Collections.sort メソッドと List.sort メソッド

現在ではより直感的に記述可能な List.sort の利用が推奨されており、Collections.sort が利用される機会は減っていますが、既存のソースを理解するために必要となるケースも想定し、両者の違いは知っておきたいところです。

まず、List.sort、Collections.sort のいずれの場合も、対象の List そのものの要素をソートすることに注意が必要です。元の List の要素の並びはそのままに、別の List にソートして格納したい場合は利用できません。

いずれのメソッドも比較順の指定には「Comparator インターフェイス」を用います。特に、数値や文字列のように単純な比較を行う場合は Comparator インターフェースのメソッドを使って順序(昇順・降順)を指定できます。

このとき、List.sort では必ず引数に Comparator の指定が必要となるのに対し、Collections.sort の場合は自然順序(昇順)の場合 Comparator の指定が省略可能であることに注意してください。

まず、文字列(String)のリストをソートしてみましょう。

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

public class SortComparisonExample {
    public static void main(String[] args) {
    
        // 比較のために同じ内容のリストを2つ用意
        List<String> listOld = new ArrayList<>();
        listOld.add("Banana");
        listOld.add("Apple");
        listOld.add("Cherry");

        // listNew に listOld の内容をコピー
        List<String> listNew = new ArrayList<>(listOld);

        System.out.println("--- 1. 昇順(A → Z)の比較 ---");
        
        // 【Old】 Collections.sort を利用
        // 引数が1つの場合は自然順序(昇順)になる
        Collections.sort(listOld);
        System.out.println("Old style: " + listOld);

        // 【New】 List.sort を利用
        // Comparator.naturalOrder() で明示的に自然順序を指定
        listNew.sort(Comparator.naturalOrder());
        System.out.println("New style: " + listNew);


        System.out.println("\n--- 2. 降順(Z → A)の比較 ---");
        
        // 【Old】 Collections.sort を利用
        // 第2引数に Collections.reverseOrder() を渡す
        Collections.sort(listOld, Collections.reverseOrder());
        System.out.println("Old style: " + listOld);

        // 【New】 List.sort を利用
        // 引数に Comparator.reverseOrder() を渡す
        listNew.sort(Comparator.reverseOrder());
        System.out.println("New style: " + listNew);
    }
}


実行結果:

--- 1. 昇順(A → Z)の比較 ---
Old style: [Apple, Banana, Cherry]
New style: [Apple, Banana, Cherry]

--- 2. 降順(Z → A)の比較 ---
Old style: [Cherry, Banana, Apple]
New style: [Cherry, Banana, Apple]


次に、数値のリストで同じように実行してみます。

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

public class NumberComparisonExample {
    public static void main(String[] args) {
        // 比較のために同じ内容のリストを2つ用意
        List<Integer> listOld = new ArrayList<>(List.of(10, 5, 20, 8));
        List<Integer> listNew = new ArrayList<>(listOld);

        System.out.println("--- 1. 昇順(小さい順)の比較 ---");
        
        // 【Old】 Collections.sort を利用
        // 引数が1つの場合は自然順序(昇順)になる(Comparator省略可)
        Collections.sort(listOld);
        System.out.println("Collections.sort: " + listOld);

        // 【New】 List.sort を利用
        // Comparator.naturalOrder() で明示的に自然順序を指定する(引数必須)
        listNew.sort(Comparator.naturalOrder());
        System.out.println("List.sort       : " + listNew);


        System.out.println("\n--- 2. 降順(大きい順)の比較 ---");
        
        // 【Old】 Collections.sort を利用
        // 第2引数に Collections.reverseOrder() を渡す
        Collections.sort(listOld, Collections.reverseOrder());
        System.out.println("Collections.sort: " + listOld);

        // 【New】 List.sort を利用
        // 引数に Comparator.reverseOrder() を渡す
        listNew.sort(Comparator.reverseOrder());
        System.out.println("List.sort       : " + listNew);
    }
}


実行結果:

--- 1. 昇順(小さい順)の比較 ---
Collections.sort: [5, 8, 10, 20]
List.sort       : [5, 8, 10, 20]

--- 2. 降順(大きい順)の比較 ---
Collections.sort: [20, 10, 8, 5]
List.sort       : [20, 10, 8, 5]

Comparator の利用

オブジェクトのソート(単一条件)

独自の Java Bean クラスなどのオブジェクトのリストの場合、数値や文字列とは異なり、Java が自動的に順序を判断することができません。そのため、「どの項目(フィールド)で並び替えるか」を明示的に指定する必要があります。

このような場合、Comparator.comparing メソッドを使用できます。このメソッドを使うことで、「User クラスの age(年齢)フィールドで比較する」といった独自の指定を、メソッド参照(::)を用いて簡潔に記述できます。

まず、メンバーに name(文字列)と age(int)を持つ bean クラス User があるとします。

public class User {
    String name;
    int age;

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

    // 結果を見やすくするためにtoStringをオーバーライド
    @Override
    public String toString() {
        return name + "(" + age + ")";
    }

    // age の getterメソッド
    public int getAge() { return age; }
    
    // name の getterメソッド
    public String getName() { return name; }
}


この User を複数格納した List に対して、List.sort メソッドと Comparator.comparing メソッドを利用し User の年齢を利用順にソートします。

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

public class ObjectSortExample {
    public static void main(String[] args) {
        List<User> users = new ArrayList<>();
        users.add(new User("Tanaka", 25));
        users.add(new User("Suzuki", 20));
        users.add(new User("Sato", 30));

        System.out.println("元のリスト: " + users);

        // 【昇順】 年齢(age)でソート
        // 「UserクラスのgetAgeメソッドの値」を使って比較する
        users.sort(Comparator.comparing(User::getAge));
        System.out.println("年齢昇順  : " + users);

        // 【降順】 年齢(age)でソート(reversedを利用)
        // 最後に reversed メソッドで順序を反転
        users.sort(Comparator.comparing(User::getAge).reversed());
        System.out.println("年齢降順  : " + users);
    }
}


実行結果:

元のリスト: [Tanaka(25), Suzuki(20), Sato(30)]
年齢昇順  : [Suzuki(20), Tanaka(25), Sato(30)]
年齢降順  : [Sato(30), Tanaka(25), Suzuki(20)]


ここでは、年齢の昇順でソートをしているため、昇順、降順の指定を省略していますが、comparing メソッドの引数で明示的に順序を指定することもできます。

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

public class ObjectSortExample2 {
    public static void main(String[] args) {
        List<User> users = new ArrayList<>();
        users.add(new User("Tanaka", 25));
        users.add(new User("Suzuki", 20));
        users.add(new User("Sato", 30));

        System.out.println("元のリスト: " + users);

        // 【昇順】 年齢(age)でソート
        // Comparator.naturalOrder を指定
        users.sort(Comparator.comparing(User::getAge, Comparator.naturalOrder()));
        System.out.println("年齢昇順  : " + users);

        // 【降順】 年齢(age)でソート
        // Comparator.reverseOrder を指定
        users.sort(Comparator.comparing(User::getAge, Comparator.reverseOrder()));
        System.out.println("年齢降順  : " + users);
    }
}

オブジェクトのソート(複数条件)

Comparator をメソッドチェーン(鎖のように繋げて書く方法)として記述することで、複数の条件を指定したソートを行うこともできます。

具体的には、Comparator.thenComparing メソッドを利用することで、「年齢順に並べたいが、もし年齢が同じだった場合は、名前順(あいうえお順)に並べたい」というように、優先順位をつけて複数の条件を指定することが可能です。

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

public class MultiSortExample {
    public static void main(String[] args) {
        List<User> users = new ArrayList<>();
        users.add(new User("Tanaka", 25));
        users.add(new User("Suzuki", 25));
        users.add(new User("Ando", 20));

        System.out.println("元のリスト: " + users);

        // 【複数条件ソート】
        // 1. まず年齢(Age)で比較
        // 2. 年齢が同じなら、名前(Name)で比較
        users.sort(Comparator.comparing(User::getAge)
                             .thenComparing(User::getName));
        
        System.out.println("ソート結果: " + users);
    }
}


実行結果:

元のリスト: [Tanaka(25), Suzuki(25), Ando(20)]
ソート結果: [Ando(20), Suzuki(25), Tanaka(25)]


thenComparing メソッドも、第二引数で昇順、降順の指定をすることが可能です。以下の例のように、年齢を降順、名前を昇順に指定することもできます。

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

public class MultiSortExample {
    public static void main(String[] args) {
        List<User> users = new ArrayList<>();
        users.add(new User("Tanaka", 25));
        users.add(new User("Suzuki", 25));
        users.add(new User("Ando", 20));

        System.out.println("元のリスト: " + users);

        // 【複数条件ソート】
        // 1. まず年齢(Age)の降順で比較
        // 2. 年齢が同じなら、名前(Name)の昇順で比較
        users.sort(Comparator.comparing(User::getAge, Comparator.reverseOrder())
                             .thenComparing(User::getName, Comparator.naturalOrder()));
        
        System.out.println("ソート結果: " + users);
    }
}


実行結果:

元のリスト: [Tanaka(25), Suzuki(25), Ando(20)]
ソート結果: [Suzuki(25), Tanaka(25), Ando(20)]


この thenComparing メソッドは、何度も繰り返してつなげることができるため、もっと複雑なソート順序が必要な場合でも対応することができます。


本記事では、Collections.sort および List.sort メソッドを利用した基本的なソート方法についてご説明しましたが、いかがでしたでしょうか。次回の記事では、Stream API を利用したソート手順について説明します。

株式会社GSI 採用サイト

新しいこと、始めよう

あなたとともに歩を進めるWEBメディア