Java – Streamで複数条件でソートする方法
JavaのStreamを使用して複数条件でソートするには、Comparatorを組み合わせます。
ComparatorのthenComparingメソッドを利用することで、優先順位に基づいた複数条件のソートが可能です。
たとえば、最初に年齢で昇順、次に名前で辞書順にソートする場合、Comparator.comparing(Person::getAge).thenComparing(Person::getName)のように記述します。
これをsortedメソッドに渡すことで、Stream内の要素を複数条件で並べ替えることができます。
Streamでのソートの基本
JavaのStream APIを使用すると、コレクションの要素を簡単に操作できます。
その中でも、ソートは非常に一般的な操作です。
Streamを使ったソートの基本的な方法について解説します。
Streamの基本的な使い方
Streamを使用するためには、まずコレクションからStreamを生成する必要があります。
以下のサンプルコードでは、リストからStreamを生成し、ソートを行います。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class App {
    public static void main(String[] args) {
        // サンプルデータの作成
        List<String> names = Arrays.asList("田中", "佐藤", "鈴木", "高橋", "山田");
        // Streamを使ってソート
        List<String> sortedNames = names.stream()
            .sorted() // 自然順序でソート
            .collect(Collectors.toList());
        // 結果の出力
        System.out.println(sortedNames);
    }
}[佐藤, 鈴木, 高橋, 田中, 山田]ソートの種類
Stream APIでは、以下のようなソートが可能です。
| ソートの種類 | 説明 | 
|---|---|
| 自然順序 | Comparableインターフェースに基づく順序でソート | 
| カスタム順序 | Comparatorを使用して独自の順序でソート | 
自然順序でのソート
上記の例では、sorted()メソッドを使用して自然順序でソートしました。
これは、文字列や数値などのデフォルトの順序に従います。
カスタム順序でのソート
カスタム順序でソートする場合は、sorted(Comparator)メソッドを使用します。
次のサンプルコードでは、文字列の長さに基づいてソートを行います。
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class App {
    public static void main(String[] args) {
        // サンプルデータの作成
        List<String> names = Arrays.asList("田中", "佐藤", "鈴木", "高橋", "山田");
        // 文字列の長さでソート
        List<String> sortedByLength = names.stream()
            .sorted(Comparator.comparingInt(String::length)) // 文字列の長さでソート
            .collect(Collectors.toList());
        // 結果の出力
        System.out.println(sortedByLength);
    }
}[田中, 佐藤, 鈴木, 高橋, 山田]このように、Stream APIを使用することで、簡単にコレクションの要素をソートすることができます。
次のセクションでは、複数条件でのソートについて詳しく解説します。
実践:複数条件でのソートの例
複数条件でのソートは、特定の要件に基づいてデータを整理する際に非常に便利です。
JavaのStream APIを使用すると、簡単に複数の条件でソートを行うことができます。
ここでは、複数の条件を使ったソートの具体例を示します。
サンプルデータの準備
まず、ソート対象となるカスタムクラスを作成します。
このクラスは、名前と年齢を持つシンプルなものです。
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
class Person {
    String name;
    int age;
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return name + " (" + age + "歳)";
    }
}複数条件でのソート
次に、Personクラスのリストを年齢で昇順、同じ年齢の場合は名前で昇順にソートします。
以下のサンプルコードを見てみましょう。
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class App {
    public static void main(String[] args) {
        // サンプルデータの作成
        List<Person> people = Arrays.asList(
            new Person("田中", 25),
            new Person("佐藤", 30),
            new Person("鈴木", 25),
            new Person("高橋", 30),
            new Person("山田", 20)
        );
        // 年齢で昇順、同じ年齢の場合は名前で昇順にソート
        List<Person> sortedPeople = people.stream()
            .sorted(Comparator.comparingInt(Person::age)
                .thenComparing(Person::name)) // 複数条件でソート
            .collect(Collectors.toList());
        // 結果の出力
        System.out.println(sortedPeople);
    }
}[山田 (20歳), 田中 (25歳), 鈴木 (25歳), 佐藤 (30歳), 高橋 (30歳)]このコードでは、Comparator.comparingInt(Person::age)を使用して年齢でソートし、thenComparing(Person::name)を使って同じ年齢の人を名前でソートしています。
これにより、年齢が同じ場合でも、名前のアルファベット順で整理されます。
このように、Stream APIを利用することで、複数の条件に基づいた柔軟なソートが可能になります。
次のセクションでは、さらに柔軟なソート条件の実現方法について解説します。
応用:柔軟なソート条件の実現
JavaのStream APIを使用すると、柔軟なソート条件を簡単に実現できます。
ここでは、条件に応じて異なるソートを行う方法や、動的にソート条件を変更する方法について解説します。
条件に応じたソートの実装
特定の条件に基づいてソートを変更する場合、Comparatorを使って条件を組み合わせることができます。
以下のサンプルコードでは、年齢が30歳以上の人を優先的にソートし、同じ年齢の場合は名前でソートします。
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
class Person {
    String name;
    int age;
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // ageのゲッターメソッド
    public int getAge() {
        return age;
    }
    // nameのゲッターメソッド
    public String getName() {
        return name;
    }
    @Override
    public String toString() {
        return name + " (" + age + "歳)";
    }
}
public class App {
    public static void main(String[] args) {
        // サンプルデータの作成
        List<Person> people = Arrays.asList(
                new Person("田中", 25),
                new Person("佐藤", 30),
                new Person("鈴木", 35),
                new Person("高橋", 30),
                new Person("山田", 20));
        // 年齢が30歳以上の人を優先し、同じ年齢の場合は名前でソート
        List<Person> sortedPeople = people.stream()
                .sorted(Comparator.comparingInt((Person p) -> p.age >= 30 ? 0 : 1) // 年齢が30歳以上を優先
                        .thenComparing(Person::getAge) // 年齢でソート
                        .thenComparing(Person::getName)) // 名前でソート
                .collect(Collectors.toList());
        // 結果の出力
        System.out.println(sortedPeople);
    }
}
[佐藤 (30歳), 鈴木 (35歳), 田中 (25歳), 高橋 (30歳), 山田 (20歳)]このコードでは、Comparator.comparingInt((Person p) -> p.age >= 30 ? 0 : 1)を使用して、年齢が30歳以上の人を優先的にソートしています。
次に、thenComparing(Person::age)で年齢でソートし、最後にthenComparing(Person::name)で名前でソートしています。
このように、条件に応じて柔軟にソートを行うことができます。
動的なソート条件の実現
さらに、動的にソート条件を変更することも可能です。
以下のサンプルコードでは、ユーザーの入力に基づいてソート条件を変更します。
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
class Person {
    String name;
    int age;
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // ageのゲッターメソッド
    public int getAge() {
        return age;
    }
    // nameのゲッターメソッド
    public String getName() {
        return name;
    }
    @Override
    public String toString() {
        return name + " (" + age + "歳)";
    }
}
public class App {
    public static void main(String[] args) {
        // サンプルデータの作成
        List<Person> people = Arrays.asList(
                new Person("田中", 25),
                new Person("佐藤", 30),
                new Person("鈴木", 35),
                new Person("高橋", 30),
                new Person("山田", 20));
        // ユーザーからの入力を受け取る
        Scanner scanner = new Scanner(System.in);
        System.out.println("ソート条件を選択してください (1: 年齢, 2: 名前): ");
        int choice = scanner.nextInt();
        // 動的にソート条件を変更
        List<Person> sortedPeople = people.stream()
                .sorted((choice == 1) ? Comparator.comparingInt(Person::getAge) : Comparator.comparing(Person::getName))
                .collect(Collectors.toList());
        // 結果の出力
        System.out.println(sortedPeople);
    }
}ソート条件を選択してください (1: 年齢, 2: 名前): 
1
[山田 (20歳), 田中 (25歳), 佐藤 (30歳), 高橋 (30歳), 鈴木 (35歳)]このコードでは、ユーザーの入力に基づいてソート条件を変更しています。
choiceの値によって、年齢でソートするか名前でソートするかを決定します。
このように、動的に条件を変更することで、より柔軟なソートが可能になります。
このように、JavaのStream APIを使用することで、柔軟なソート条件を簡単に実現できます。
これにより、さまざまな要件に応じたデータの整理が可能になります。
まとめ
この記事では、JavaのStream APIを使用したソートの基本から、複数条件でのソート、さらには柔軟なソート条件の実現方法について詳しく解説しました。
Stream APIを活用することで、データの整理や表示が効率的に行えるため、プログラミングの実践において非常に役立つ技術です。
ぜひ、実際のプロジェクトや学習の中でこれらのテクニックを試してみて、より効果的なデータ処理を実現してください。
 
![[Java] Streamで日付をもとにソートする方法(昇順/降順)](https://af-e.net/wp-content/uploads/2024/11/thumbnail-51241.png)
![[Java] Streamで終端処理を実装する方法](https://af-e.net/wp-content/uploads/2024/11/thumbnail-51248.png)
![[Java] Streamの使いどころをわかりやすく紹介](https://af-e.net/wp-content/uploads/2024/11/thumbnail-51247.png)
![[Java] Streamで2つのコレクションを結合する方法](https://af-e.net/wp-content/uploads/2024/11/thumbnail-51246.png)
![[Java] Streamで特定の値で昇順ソートする方法](https://af-e.net/wp-content/uploads/2024/11/thumbnail-51240.png)
![[Java] Stream APIで降順ソートする方法](https://af-e.net/wp-content/uploads/2024/11/thumbnail-51239.png)
![[Java] Streamを使ってnull値を考慮したソートをする方法](https://af-e.net/wp-content/uploads/2024/11/thumbnail-51238.png)
![[Java] Stream APIでグルーピング(gtoupingby)する方法](https://af-e.net/wp-content/uploads/2024/11/thumbnail-51237.png)
![[Java] Streamで2つのMapを結合する方法](https://af-e.net/wp-content/uploads/2024/11/thumbnail-51233.png)
![[Java] Streamで2つのListを結合する方法](https://af-e.net/wp-content/uploads/2024/11/thumbnail-51230.png)
![[Java] Streamでよく使うメソッドまとめ](https://af-e.net/wp-content/uploads/2024/11/thumbnail-51254.png)
![[Java] Streamと配列を相互に変換する方法](https://af-e.net/wp-content/uploads/2024/11/thumbnail-51249.png)