Comparator とラムダによるソート
ラムダ式と Comparator.comparing のファクトリーメソッドで Comparator のインスタンスを作成します。
「Comparator とラムダによるソート」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
Comparator とラムダによるソート
Comparator<T> は、オブジェクトの外部順序を定義します。Comparable とは異なり、クラスを変更せずに必要な数だけ Comparator を作成できます。
Comparator の作成
ラムダまたはメソッド参照で Comparator を作成し、ソートメソッドに渡します。
import java.util.*;
record Product(String name, double price, int stock) {}
List<Product> products = new ArrayList<>(List.of(
new Product("Mouse", 29.99, 50),
new Product("Laptop", 999.00, 5),
new Product("USB Hub", 24.99, 100)
));
// Lambda comparator
products.sort((a, b) -> Double.compare(a.price(), b.price()));
System.out.println(products);
// [USB Hub, Mouse, Laptop] (by price ascending)Comparator.comparing ファクトリ
Comparator.comparing(keyExtractor) は、キー抽出関数から Comparator を作成します。直接ラムダを書くよりも簡潔です。
import java.util.Comparator;
Comparator<Product> byPrice = Comparator.comparingDouble(Product::price);
Comparator<Product> byName = Comparator.comparing(Product::name);
Comparator<Product> byStock = Comparator.comparingInt(Product::stock);
products.sort(byPrice);
System.out.println(products); // sorted by price ascending
products.sort(byName);
System.out.println(products); // sorted alphabeticallyreversed()
reversed() は、任意の Comparator の順序を反転します。
import java.util.Comparator;
Comparator<Product> mostExpensiveFirst =
Comparator.comparingDouble(Product::price).reversed();
products.sort(mostExpensiveFirst);
System.out.println(products);
// [Laptop($999.0), Mouse($29.99), USB Hub($24.99)]naturalOrder と reverseOrder
Comparator.naturalOrder() はクラスの Comparable を使用します。reverseOrder() はその順序を反転します。
List<String> names = new ArrayList<>(List.of("Charlie", "Alice", "Bob"));
names.sort(Comparator.naturalOrder());
System.out.println(names); // [Alice, Bob, Charlie]
names.sort(Comparator.reverseOrder());
System.out.println(names); // [Charlie, Bob, Alice]
// Sort integers descending
List<Integer> nums = new ArrayList<>(List.of(5, 2, 8, 1, 9));
nums.sort(Comparator.reverseOrder());
System.out.println(nums); // [9, 8, 5, 2, 1]null に安全な Comparator
Comparator.nullsFirst() と nullsLast() を使用すると、NPE を発生させずに null 要素を処理できます。
import java.util.*;
List<String> withNulls = new ArrayList<>(Arrays.asList("Charlie", null, "Alice", null, "Bob"));
withNulls.sort(Comparator.nullsLast(Comparator.naturalOrder()));
System.out.println(withNulls); // [Alice, Bob, Charlie, null, null]
withNulls.sort(Comparator.nullsFirst(Comparator.naturalOrder()));
System.out.println(withNulls); // [null, null, Alice, Bob, Charlie]Comparator を使った Stream の sorted()
Comparator とともに中間 Stream 操作の sorted() を使用すると、関数型スタイルでソートできます。
import java.util.stream.*;
record Employee(String name, String dept, double salary) {}
List<Employee> employees = List.of(
new Employee("Alice", "Engineering", 95000),
new Employee("Bob", "Marketing", 72000),
new Employee("Charlie", "Engineering", 105000)
);
// Sort by salary descending in a stream pipeline
employees.stream()
.sorted(Comparator.comparingDouble(Employee::salary).reversed())
.forEach(e -> System.out.println(e.name() + ": $" + e.salary()));
// Charlie: $105000.0 / Alice: $95000.0 / Bob: $72000.0ラムダとメソッド参照による Comparator
キー抽出処理が単純な getter の場合は、メソッド参照を使うと Comparator をさらに簡潔に記述できます。
// Lambda
Comparator<String> c1 = (a, b) -> a.length() - b.length();
// Comparator.comparing with lambda
Comparator<String> c2 = Comparator.comparing(s -> s.length());
// Comparator.comparingInt with method reference (cleanest)
Comparator<String> c3 = Comparator.comparingInt(String::length);
List<String> words = new ArrayList<>(List.of("banana", "fig", "apple", "kiwi"));
words.sort(c3);
System.out.println(words); // [fig, kiwi, apple, banana]状態を持つ Comparator
通常、Comparator はステートレスにするべきですが、コンストラクターのパラメーターで設定を注入することもできます。
class DistanceComparator implements Comparator<String> {
private final String target;
DistanceComparator(String target) { this.target = target; }
@Override
public int compare(String a, String b) {
return Integer.compare(distance(a), distance(b));
}
private int distance(String s) { return Math.abs(s.length() - target.length()); }
}
List<String> words = new ArrayList<>(List.of("Java", "Go", "Python", "C", "Kotlin"));
words.sort(new DistanceComparator("Java"));
System.out.println(words); // closest length to "Java" first商品カタログのカスタムソート
商品のカタログを、まず在庫状況、次に価格、最後に名前の順でソートします。
import java.util.*;
record Item(String name, double price, boolean inStock) {}
List<Item> catalog = List.of(
new Item("Laptop", 999.0, true),
new Item("Case", 19.99, false),
new Item("Mouse", 29.99, true),
new Item("Monitor", 349.0, true)
);
Comparator<Item> catalogSort =
Comparator.comparing(Item::inStock).reversed() // in-stock first
.thenComparingDouble(Item::price) // then cheapest
.thenComparing(Item::name); // then alphabetical
catalog.stream().sorted(catalogSort)
.forEach(i -> System.out.printf("%s %-15s $%.2f%n",
i.inStock() ? "[Y]" : "[N]", i.name(), i.price()));Comparator を使った Arrays.sort
Arrays.sort(array, comparator) は、カスタム Comparator を使用してオブジェクト配列をソートします。
String[] words = {"banana", "fig", "apple", "kiwi", "cherry"};
// Sort by length, then alphabetically for same length
Arrays.sort(words,
Comparator.comparingInt(String::length)
.thenComparing(Comparator.naturalOrder()));
System.out.println(Arrays.toString(words));
// [fig, kiwi, apple, banana, cherry]確認問題
Comparator.comparingDouble(Product::price).reversed() は何を生成しますか?
復習: Comparator とラムダによるソート
要点:
- Comparator<T> は外部順序を定義します。必要な数だけ使用できます
- Comparator.comparing(keyExtractor) は getter から Comparator を作成します
- reversed() は任意の Comparator の順序を反転します。Comparable 型には naturalOrder()/reverseOrder() を使用します
- nullsFirst() と nullsLast() は null 要素を安全に処理します
- Stream パイプラインで sorted(comparator) を使用すると、関数型スタイルで順序付けできます
- Comparator は sort()、Arrays.sort()、TreeSet、TreeMap に渡せます
よくある質問
「Comparator とラムダによるソート」レッスンは無料ですか?
はい。「Comparator とラムダによるソート」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「Comparator とラムダによるソート」で何を学びますか?
ラムダ式と Comparator.comparing のファクトリーメソッドで Comparator のインスタンスを作成します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「Comparator とラムダによるソート」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Comparable インターフェース
- Comparator とラムダによるソート
- thenComparing による複数キーソート
- 配列とコレクションのソート実践