Collections.shuffle / sort / reverse — リスト操作ユーティリティ
リストの「並び替え」「逆順」「ランダム化」を一発でやれるのが Collections ユーティリティ。初心者でも迷わない使いどころ、コード例、落とし穴をまとめます。
基本の3メソッド
- shuffle: リスト要素の順序をランダムに並べ替える(均等なシャッフル)。
- sort: リストを昇順(自然順序)や任意の比較ルールで並べ替える。
- reverse: 現在の並びをそのまま逆順にする(単純反転)。
すぐ試せる基本例
import java.util.*;
public class ListOpsBasics {
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>(Arrays.asList(5, 3, 8, 1));
// 1) sort: 昇順(自然順序)
Collections.sort(nums); // [1, 3, 5, 8]
// 同等: nums.sort(Comparator.naturalOrder());
// 2) reverse: 逆順に反転
Collections.reverse(nums); // [8, 5, 3, 1]
// 3) shuffle: ランダムに並び替え
Collections.shuffle(nums); // 実行ごとに異なる順序
// 再現可能なシャッフル(シード指定)
Collections.shuffle(nums, new Random(42));
}
}
Javasort の使い分け(Comparator で柔軟な並べ替え)
文字列を長さ順、同じ長さは辞書順
List<String> words = new ArrayList<>(List.of("cat", "apple", "hi", "banana"));
words.sort(Comparator
.comparingInt(String::length)
.thenComparing(Comparator.naturalOrder()));
// 結果: [hi, cat, apple, banana]
Java降順(大きい順)
List<Integer> nums = new ArrayList<>(List.of(5, 3, 8, 1));
nums.sort(Comparator.reverseOrder()); // [8, 5, 3, 1]
Javaフィールドで並べ替え(オブジェクトリスト)
class User {
final String name;
final int age;
User(String name, int age) { this.name = name; this.age = age; }
public String toString() { return name + "(" + age + ")"; }
}
List<User> users = new ArrayList<>(List.of(
new User("Tanaka", 30), new User("Sato", 22), new User("Kato", 22)));
users.sort(Comparator
.comparingInt(u -> u.age)
.thenComparing(u -> u.name));
// 結果: [Kato(22), Sato(22), Tanaka(30)]
Java- ポイント: comparing / thenComparing で「主キー→副キー」の順にルール記述。
- 安定ソート: Java の sort は安定(同順位の元順序を保つ)。
shuffle の実践ポイント(再現性と配列対処)
- 均等シャッフル: Collections.shuffle はリストに対して均等なランダム並び替え。
- 再現可能: Random にシードを渡すと結果が固定され、テストしやすい。
List<String> cards = new ArrayList<>(List.of("A", "B", "C", "D"));
Collections.shuffle(cards, new Random(123)); // 毎回同じ並び
Java- 配列は直接不可: shuffle は List 用。配列なら一旦リスト化してから。
Integer[] arr = {1, 2, 3, 4, 5};
List<Integer> list = Arrays.asList(arr); // 固定長ビュー(要素は書き換え可)
Collections.shuffle(list); // 配列中身がシャッフルされる
Java- 要素追加・削除もしたいなら、まず ArrayList にコピー
List<Integer> list2 = new ArrayList<>(Arrays.asList(arr));
Collections.shuffle(list2); // こちらは add/remove も可能
Javareverse の使いどころ(単純反転)
List<String> logs = new ArrayList<>(List.of("e1", "e2", "e3"));
Collections.reverse(logs); // [e3, e2, e1]
Java- ソート後の反転: 「降順にしたい」が比較が面倒なら、昇順ソート → reverse でもOK。
- 部分反転は自前: サブリスト取得して reverse 適用
List<Integer> nums = new ArrayList<>(List.of(1,2,3,4,5,6));
Collections.reverse(nums.subList(2, 5)); // 3..5の範囲を反転 → [1,2,5,4,3,6]
Java例題で身につける
例題1: トランプの山札を作ってシャッフル
List<String> deck = new ArrayList<>();
for (String suit : List.of("♠", "♥", "♦", "♣")) {
for (int rank = 1; rank <= 13; rank++) {
deck.add(suit + rank);
}
}
Collections.shuffle(deck);
System.out.println(deck.subList(0, 5)); // 先頭5枚(毎回ランダム)
Java例題2: 顧客一覧を「購入額降順、同額は名前昇順」
class Customer { final String name; final int total; Customer(String n, int t){name=n; total=t;} }
List<Customer> cs = new ArrayList<>(List.of(
new Customer("Tanaka", 12000), new Customer("Sato", 12000), new Customer("Kato", 9000)));
cs.sort(Comparator
.comparingInt((Customer c) -> c.total).reversed()
.thenComparing(c -> c.name));
// 結果: Tanaka(12000), Sato(12000), Kato(9000)
Java例題3: 最新ログを先頭にした表示(逆順)
List<String> logs = new ArrayList<>(List.of("10:00", "10:05", "10:10"));
Collections.reverse(logs);
for (String l : logs) System.out.println(l); // 10:10 → 10:05 → 10:00
Java性能・仕様の要点
- sort: 平均計算量はだいたい O(n log n)。Java の実装は安定ソート。
- shuffle: O(n)。均等なランダム化(Fisher–Yates系)。
- reverse: O(n)。リンク構造でなければ原地反転(リストの種類に依存)。
- 破壊的操作: 3メソッドともリストを「その場で」書き換える。元の順序が必要ならコピーを作る。
List<Integer> sortedCopy = new ArrayList<>(nums);
Collections.sort(sortedCopy);
Javaよくある落とし穴と回避策
- Arrays.asList の落とし穴: 固定長ビュー。add/remove で例外。→ 変更したいなら new ArrayList<>(…) にコピー。
- ロケール依存の文字列比較: 日本語やアクセントを正しく並べたいなら Collator を使う。
import java.text.Collator;
Collator ja = Collator.getInstance(java.util.Locale.JAPAN);
words.sort(ja::compare);
Java- Comparator の null: null を含むなら nullsFirst/nullsLast を明示。
list.sort(Comparator.nullsLast(Comparator.naturalOrder()));
Java- シャッフルの再現性: テストで固定したい → Random(シード) を渡す。
- 不変リストへの適用: List.of(…) は不変。sort/reverse/shuffle は例外。→ まず可変リストへコピー。
テンプレート集
昇順・降順
list.sort(Comparator.naturalOrder()); // 昇順
list.sort(Comparator.reverseOrder()); // 降順
Java複合キー
list.sort(Comparator.comparing(Type::key1)
.thenComparing(Type::key2));
Javaカスタム比較(数値の絶対値で昇順)
list.sort(Comparator.comparingInt(Math::abs));
Java部分範囲の操作
Collections.sort(list.subList(from, to)); // 部分ソート(昇順)
Collections.reverse(list.subList(from, to)); // 部分反転
Javaシャッフル(シード指定)
Collections.shuffle(list, new Random(12345));
Javaまとめ
- 並べ替えは sort、ランダム化は shuffle、逆順は reverse。まずこの3つを使い分ければ困らない。
- Comparator を使えば「業務の並びルール」をそのままコード化できる。複合キー、降順、null対応、言語別比較を覚えておくと強い。
- 3メソッドは破壊的操作。元の順序が必要ならコピーしてから適用するのが安全。
