CodeGym /コース /JAVA 25 SELF /Java のコレクションにおける要素の検索とソート

Java のコレクションにおける要素の検索とソート

JAVA 25 SELF
レベル 29 , レッスン 4
使用可能

1. コレクションでの要素検索

標準メソッドによる検索

たとえば、名前のリストがあるとします。

List<String> names = List.of("アンナ", "ボリス", "ビクトリア", "アンナ", "ドミトリー");

Java には検索のための便利なメソッドがいくつかあります。

  • contains(Object o) — コレクションにその要素が含まれているかを確認します。
  • indexOf(Object o) — 最初に見つかった位置のインデックスを返します(見つからない場合は -1)。
  • lastIndexOf(Object o) — 最後に見つかった位置のインデックスを返します(見つからない場合は -1)。

例:

System.out.println(names.contains("アンナ"));      // true
System.out.println(names.indexOf("アンナ"));       // 0
System.out.println(names.lastIndexOf("アンナ"));   // 3
System.out.println(names.contains("セルゲイ"));    // false

豆知識: Set のようなコレクションには indexOflastIndexOf はありません — Set にはそもそもインデックスがなく、一意な値だけが保持されます。

条件による検索

特定の値ではなく、条件に合う要素を見つけたいことがあります。たとえば、6 文字より長い最初の名前を見つける、といったケースです。通常の for ループで十分で、条件に合うものが見つかったら — break を使います。

List<String> names = List.of("アンナ", "ボリス", "ビクトリア", "アンナ", "ドミトリー");

String found = null;
for (String name : names) {
    if (name.length() > 6) {
        found = name;
        break; // 最初に条件を満たす要素を見つけたので、ループを抜ける
    }
}
System.out.println(found); // ビクトリア

最大値と最小値の検索

要素が相互に比較可能(たとえば数値)なコレクションなら、クラス Collections を使って最大値・最小値をすばやく見つけられます。

List<Integer> numbers = List.of(10, 5, 20, 7, 20, 3);

int max = Collections.max(numbers); // 20
int min = Collections.min(numbers); // 3

System.out.println("最大値: " + max);
System.out.println("最小値: " + min);

重要: 要素は比較可能(Comparable を実装)である必要があります。そうでない場合はコンパレータを渡してください。

2. コレクションのソート

リストのデフォルトのソート

ソートできるのは可変のリスト(例: ArrayListLinkedList)のみです。SetMap のようなコレクションは直接のソートをサポートしていません。

デフォルトでは「自然順序」に従って並び替えます。数値なら昇順、文字列なら辞書順です。

List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
Collections.sort(numbers);
System.out.println(numbers); // [1, 3, 5, 7]

同じことをリストのメソッド sort でも行えます:

List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
numbers.sort(null); // null は自然順序を使うという意味
System.out.println(numbers); // [1, 3, 5, 7]

Comparator を使ったソート

独自の規則が必要な場合、たとえば文字列の長さでソートするには次のようにします。

List<String> words = new ArrayList<>(List.of("kot", "slon", "mukha", "nosorog"));

words.sort(Comparator.comparingInt(String::length));
System.out.println(words); // [kot, slon, mukha, nosorog]

逆順:

words.sort(Comparator.comparingInt(String::length).reversed());
System.out.println(words); // [nosorog, mukha, slon, kot]

古いスタイル( Collections.sort 経由):

Collections.sort(words, Comparator.comparingInt(String::length));

3. コレクションごとのソートの注意点

ソートで変更できるのはリストだけ

ソート用メソッド(sortCollections.sort)は、要素順序を持つコレクション(例: List)でのみ動作します。SetMap にはそのようなメソッドは用意されていません。

Set をソートしようとすると:

Set<Integer> mySet = new HashSet<>(List.of(3, 1, 2));
Collections.sort(mySet); // コンパイルエラー: sort は List を期待します!

もし Set から並び替え済みのリストが欲しい場合:

List<Integer> sortedFromSet = new ArrayList<>(mySet);
Collections.sort(sortedFromSet);
System.out.println(sortedFromSet); // [1, 2, 3]

Map のソート: キーまたは値で並べ替える

Map 自体を直接ソートすることはできませんが、次のようにすれば可能です。

  • キーと値のペア(エントリ)のリストを取得する
  • 必要な規則でそのリストをソートする
  • 必要に応じて新しい Map に組み立て直す

例: 値でソート

Map<String, Integer> scores = Map.of(
    "アンナ", 15,
    "ボリス", 20,
    "ヴィカ", 12
);

List<Map.Entry<String, Integer>> entries = new ArrayList<>(scores.entrySet());
entries.sort(Map.Entry.comparingByValue());

for (Map.Entry<String, Integer> entry : entries) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}
// ヴィカ: 12
// アンナ: 15
// ボリス: 20

オブジェクトをフィールドでソートする

たとえば、次のようなユーザークラスがあるとします。

class User {
    String name;
    int age;
    User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

そしてユーザーのリスト:

List<User> users = new ArrayList<>(List.of(
    new User("アンナ", 22),
    new User("ボリス", 18),
    new User("ヴィカ", 25)
));

年齢でソート:

users.sort(Comparator.comparingInt(u -> u.age));
System.out.println(users); // [ボリス (18), アンナ (22), ヴィカ (25)]

逆順:

users.sort(Comparator.comparingInt((User u) -> u.age).reversed());
System.out.println(users); // [ヴィカ (25), アンナ (22), ボリス (18)]

4. 検索とソートでよくあるミス

誤りその1: 不変リストをソートしようとする。 List.of(...) で作られたリストは変更できません — sort を呼ぶと UnsupportedOperationException が送出されます。

List<Integer> immutable = List.of(3, 1, 2);
immutable.sort(null); // 例外がスローされる!

誤りその2: Set や Map を直接ソートする。 ソート用メソッドは SetMap では動作しません。並べ替えたい場合は、まずデータをリストに変換してください。

誤りその3: オブジェクトの比較方法が不適切。 比較のために整数をそのまま減算してはいけません — オーバーフローの可能性があります。u1.age - u2.age の代わりに Integer.compareComparator.comparingInt を使用しましょう。

// users.sort((u1, u2) -> u1.age - u2.age); // 動くには動くが、オーバーフローの危険あり!

誤りその4: 複雑な検索に contains を使う。 メソッド contains は完全一致(equals)だけを判定します。部分文字列やオブジェクトの特定フィールドで探したい場合は、条件チェック付きのループや Comparator/Stream を使ってください。

1
タスク
JAVA 25 SELF, レベル 29, レッスン 4
ロック未解除
森での動物の出現を追跡 🌲🐾
森での動物の出現を追跡 🌲🐾
1
タスク
JAVA 25 SELF, レベル 29, レッスン 4
ロック未解除
ゲームリーグの試合結果の分析 🎮📊
ゲームリーグの試合結果の分析 🎮📊
1
アンケート/クイズ
コンパレータとオブジェクトの比較、レベル 29、レッスン 4
使用不可
コンパレータとオブジェクトの比較
コンパレータとオブジェクトの比較
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION