0Pricing
Java Academy · レッスン

配列とコレクションのソート実践

実際の例を使い、商品リスト、リーダーボード、イベント予定表にソートを適用します。

「配列とコレクションのソート実践」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。

実践的なソート

このレッスンでは、商品カタログ、ランキング、イベントのスケジュール、検索結果の順位付けなど、現実的なシナリオにソート技法を適用します。

プリミティブ配列に対する Arrays.sort

プリミティブ配列に対する Arrays.sort() はデュアルピボット・クイックソートを使用し、平均計算量は O(n log n) と非常に高速です。

int[] scores = {45, 90, 78, 62, 88, 33};
Arrays.sort(scores);
System.out.println(Arrays.toString(scores)); // [33, 45, 62, 78, 88, 90]

// Sort a range only
int[] data = {9, 3, 7, 1, 5};
Arrays.sort(data, 1, 4); // sort indices 1-3 only
System.out.println(Arrays.toString(data)); // [9, 1, 3, 7, 5]

オブジェクト配列に対する Arrays.sort

オブジェクト配列では、Arrays.sort() は TimSort(安定ソート)を使用します。カスタムの順序を指定するには Comparator を渡せます。

String[] names = {"Charlie", "Alice", "Bob", "Diana"};
Arrays.sort(names);
System.out.println(Arrays.toString(names)); // [Alice, Bob, Charlie, Diana]

// Custom order: by length, then alphabetically
Arrays.sort(names, Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()));
System.out.println(Arrays.toString(names)); // [Bob, Alice, Diana, Charlie]

Collections.sort と List.sort

どちらも List をその場でソートします。現在は List.sort() が推奨される方法です。

List<Integer> nums = new ArrayList<>(List.of(5, 2, 8, 1, 9, 3));

// Old way
Collections.sort(nums);
System.out.println(nums); // [1, 2, 3, 5, 8, 9]

// Modern way (same result)
nums.sort(Comparator.naturalOrder());
nums.sort(null); // null means natural order

// Descending
nums.sort(Comparator.reverseOrder());
System.out.println(nums); // [9, 8, 5, 3, 2, 1]

関数型スタイルの Stream.sorted()

パイプラインを構築するときは stream().sorted() を使用します。元のデータを変更せず、新しいソート済みストリームを生成します。

List<String> cities = List.of("Tokyo", "London", "New York", "Paris", "Sydney");

// Sorted stream — source list unchanged
List<String> sorted = cities.stream()
    .sorted(Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()))
    .collect(Collectors.toList());

System.out.println(sorted);
// [Paris, Tokyo, London, Sydney, New York]

値による Map のソート

面接でよく出る質問です。stream と Comparator を使用して、Map を値でソートします。

import java.util.*;
import java.util.stream.*;

Map<String, Integer> scores = Map.of(
    "Alice", 95, "Bob", 87, "Charlie", 92, "Diana", 87
);

Map<String, Integer> sorted = scores.entrySet().stream()
    .sorted(Map.Entry.<String, Integer>comparingByValue(Comparator.reverseOrder())
        .thenComparing(Map.Entry.comparingByKey()))
    .collect(Collectors.toLinkedHashMap(
        Map.Entry::getKey, Map.Entry::getValue,
        (v1, v2) -> v1, LinkedHashMap::new));

sorted.forEach((k, v) -> System.out.println(k + ": " + v));
// Alice: 95 / Charlie: 92 / Bob: 87 / Diana: 87

ロケールに対応した Collator によるソート

言語に対応した文字列ソートには、String.compareTo の代わりに java.text.Collator を使用します。アクセント、大文字と小文字、ロケール固有の順序を処理できます。

import java.text.*;
import java.util.*;

List<String> names = new ArrayList<>(List.of("éclair", "apple", "Über", "banana"));

Collator collator = Collator.getInstance(Locale.GERMAN);
names.sort(collator);
System.out.println(names); // locale-aware sort

複数の条件によるオブジェクトのソート

EC 商品のソート例です。在庫ありを先にし、次にセール価格、評価、商品名の順でソートします。

record Product(String name, double price, double salePrice, double rating, boolean inStock) {}

Comparator<Product> bestFirst = Comparator
    .comparing(Product::inStock).reversed()           // in-stock first
    .thenComparingDouble(Product::salePrice)          // cheapest sale price
    .thenComparingDouble(Product::rating).reversed()  // highest rated
    .thenComparing(Product::name);                    // alphabetical tiebreak

日付と時刻によるイベントのソート

Comparable を実装する java.time 型を使用して、イベントのスケジュールを時系列順にソートします。

import java.time.*;
import java.util.*;

record Event(String title, LocalDate date, LocalTime time) {}

List<Event> schedule = new ArrayList<>(List.of(
    new Event("Workshop",  LocalDate.of(2024,7,15), LocalTime.of(9, 0)),
    new Event("Keynote",   LocalDate.of(2024,7,14), LocalTime.of(10, 30)),
    new Event("Lunch Talk",LocalDate.of(2024,7,15), LocalTime.of(12, 0)),
    new Event("Hackathon", LocalDate.of(2024,7,14), LocalTime.of(9, 0))
));

schedule.sort(Comparator.comparing(Event::date).thenComparing(Event::time));
schedule.forEach(e -> System.out.println(e.date() + " " + e.time() + " " + e.title()));

ソートによる上位 N 個の要素の取得

上位 N 個の要素を効率的に見つけるには、降順にソートして最初の N 個を取得するか、大規模なデータセットでは PriorityQueue を使用します。

List<Integer> values = List.of(42, 17, 88, 5, 73, 56, 91, 33);

// Simple approach: sort descending, take first 3
List<Integer> top3 = values.stream()
    .sorted(Comparator.reverseOrder())
    .limit(3)
    .collect(Collectors.toList());
System.out.println(top3); // [91, 88, 73]

// For very large datasets: PriorityQueue min-heap approach is O(n log k)
import java.util.PriorityQueue;
PriorityQueue<Integer> heap = new PriorityQueue<>(3);
for (int v : values) {
    heap.offer(v);
    if (heap.size() > 3) heap.poll();
}
System.out.println(new TreeSet<>(heap).descendingSet()); // [73, 88, 91]

ソートによる重複除去

ソート後は重複要素が隣り合うため、O(n) で検出できます。

int[] arr = {3, 1, 4, 1, 5, 9, 2, 6, 5};
Arrays.sort(arr); // sort first

// Remove duplicates in O(n) after sorting
int[] unique = Arrays.stream(arr).distinct().toArray();
System.out.println(Arrays.toString(unique)); // [1, 2, 3, 4, 5, 6, 9]

パフォーマンス:ソート方法の選択

適切なソート方法を選択します:

  • プリミティブ配列:Arrays.sort() — 最速の、その場で実行するクイックソート
  • Comparable を実装したオブジェクト配列やリスト:Collections.sort() または List.sort(null)
  • 複数の順序:thenComparing による Comparator のチェーン
  • 大規模なストリームから上位 N 個を取得:PriorityQueue または Stream.sorted().limit(N)

クイックチェック

Java は Arrays.sort() でオブジェクト配列をソートするとき、どのソートアルゴリズムを使用しますか?

まとめ:実践での配列とコレクションのソート

重要なポイント:

  • プリミティブ型では Arrays.sort() がデュアルピボット・クイックソートを使用し、オブジェクトでは TimSort(安定ソート)を使用します
  • List.sort(comparator) と Collections.sort() は、どちらも安定した TimSort です
  • stream().sorted() は元のデータを変更せず、新しいソート済みストリームを生成します
  • Map を値でソートするには:entrySet().stream().sorted(Map.Entry.comparingByValue())
  • ロケールに対応した文字列ソートには Collator を使用します
  • 大規模なデータから上位 N 個を取得する場合、容量 k の PriorityQueue は完全なソートより効率的です

よくある質問

「配列とコレクションのソート実践」レッスンは無料ですか?

はい。「配列とコレクションのソート実践」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。

「配列とコレクションのソート実践」で何を学びますか?

実際の例を使い、商品リスト、リーダーボード、イベント予定表にソートを適用します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Java Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「配列とコレクションのソート実践」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このJava Academyレッスンでコードを書いて実行できますか?

はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Comparable インターフェース
  2. Comparator とラムダによるソート
  3. thenComparing による複数キーソート
  4. 配列とコレクションのソート実践
← Java Academyに戻る