Kodrill

コレクションとジェネリクス

Java SE 17 Gold (1Z0-826-JPN) 試験

オートボクシング/List・Set・Map・Deque/総称型とワイルドカード/Comparator によるソート/コレクションの便利なメソッド

問題数
18 問
合格ライン
65%
実行して確認済み
17 問
この分野の要点を読む6 章・約 20 分。実行して確かめたコード例と、試験でよくある引っかけをまとめています

ログインなしで試す

無料の 5 問を、1問ごとに正誤と解説を見ながら解けます。解答は保存されません。

5 問を試す

無料登録して学習を記録する

学習履歴・ダッシュボード・ブックマーク・模試モードが使えます。

★ 残り 13 問はプレミアム会員限定です

無料プランでは先頭 5 問まで解けます。プレミアムなら全問題・苦手問題の復習・広告非表示が使えます。
料金プランを見る

問題と解説を見る (無料)

登録しなくても、次の5問は問題文と解説をそのまま読めます。

コレクションとジェネリクスの要点

内容の確認日: 2026-10-04

この分野では、コレクション・フレームワークの主要なインタフェースとクラスの使い分け、総称型 (ジェネリクス) の型の互換性、Comparator による並べ替えが問われます。API のメソッドが「何を返すか」「元のコレクションを変えるか」を正確に覚えているかが得点の分かれ目です。

出題項目は「オート・ボクシングの使用」「コレクション・フレームワークの概要と主要なコレクション・インタフェース (List, Map, Set および Deque) の使用」「総称型の使用」「Comparator インタフェースを使用したコレクションのソート」「コレクション用の便利なメソッドの使用」の 5 つです。

オートボクシングとアンボクシング

int から Integer への自動変換 (オートボクシング) には Integer.valueOf が使われます。valueOf は -128 〜 127 の値をキャッシュしているので、この範囲の値は同じオブジェクトになり、== で比べると true になります。範囲外の値は別のオブジェクトになるので、値の比較には equals を使います。

Main.java
public class Main {    public static void main(String[] args) {        Integer a = 127, b = 127;        Integer c = 128, d = 128;        System.out.println(a == b);        System.out.println(c == d);        System.out.println(c.equals(d));    }}
ターミナル
java Main
true
false
true

オートボクシングが行うのは「プリミティブ型 → 対応するラッパー型」の変換だけです。拡大変換とボクシングを続けて行うことはできないので、int のリテラル 10 を Long 型の変数に代入するとコンパイルエラーです (10L なら可)。

Main.java
public class Main {    public static void main(String[] args) {        Long n = 10;        System.out.println(n);    }}
ターミナル
javac Main.java

コンパイルエラー (3 行目): int の 10 は Long に変換できない (int → long → Long の 2 段階の変換は行われない)

ラッパー型の値が null のときにアンボクシングが起きると、NullPointerException が発生します。Map の get は存在しないキーに対して null を返すので、そのまま計算に使うと危険です。getOrDefault を使うと安全です。

Main.java
import java.util.HashMap;import java.util.Map;​public class Main {    public static void main(String[] args) {        Map<String, Integer> stock = new HashMap<>();        stock.put("apple", 3);        System.out.println(stock.getOrDefault("lemon", 0) + 1);        int total = stock.get("lemon") + 1;        System.out.println(total);    }}
ターミナル
java Main
1

実行時に例外が発生: NullPointerException

List・Set・Map・Deque の使い分け

主なインタフェースと実装クラスの特徴は次のとおりです。

・List: 順序あり・重複可。ArrayList (添字での読み取りが速い)、LinkedList ・Set: 重複なし。HashSet (順序なし)、LinkedHashSet (追加した順)、TreeSet (並べ替えた順) ・Map: キーと値の組。キーは重複なし。HashMap、LinkedHashMap、TreeMap (キーの順) ・Deque: 先頭と末尾の両方から出し入れできるキュー。ArrayDeque、LinkedList

Deque はメソッドが多く、先頭・末尾のどちらを操作するかを取り違えやすいので注意が必要です。push・pop・offerFirst・pollFirst は先頭、offer・add・offerLast・pollLast は末尾を操作します。peek は先頭の要素を取り出さずに返します。

Main.java
import java.util.ArrayDeque;import java.util.Deque;​public class Main {    public static void main(String[] args) {        Deque<Integer> dq = new ArrayDeque<>();        dq.offer(1);        dq.offer(2);        dq.push(0);        dq.offerFirst(-1);        System.out.println(dq);        System.out.println(dq.pop() + " " + dq.pollLast());        System.out.println(dq);    }}
ターミナル
java Main
[-1, 0, 1, 2]
-1 2
[0, 1]

TreeMap (と TreeSet) には、キーの大小で検索するメソッドがあります。ceilingKey(k) は k 以上で最小のキー、floorKey(k) は k 以下で最大のキーを返します。headMap(k) は k より小さい (k を含まない) 部分、tailMap(k) は k 以上 (k を含む) 部分です。

Main.java
import java.util.Map;import java.util.TreeMap;​public class Main {    public static void main(String[] args) {        TreeMap<Integer, String> map = new TreeMap<>(Map.of(10, "a", 20, "b", 30, "c"));        System.out.println(map.ceilingKey(15) + " " + map.floorKey(15));        System.out.println(map.headMap(20) + " " + map.tailMap(20));        System.out.println(map.firstEntry().getValue());    }}
ターミナル
java Main
20 10
{10=a} {20=b, 30=c}
a

変更できないリストにも 2 種類あります。Arrays.asList が返すリストは元の配列と結び付いた固定長のリストで、set による置き換えはできますが、add・remove はできません。List.of が返すリストは完全に変更できず、set も UnsupportedOperationException になります。

Main.java
import java.util.Arrays;import java.util.List;​public class Main {    public static void main(String[] args) {        List<String> fixed = Arrays.asList("a", "b");        fixed.set(0, "x");        System.out.println(fixed);        List<String> immutable = List.of("a", "b");        immutable.set(0, "x");    }}
ターミナル
java Main
[x, b]

実行時に例外が発生: UnsupportedOperationException

総称型とワイルドカード

総称型は、型引数が違えば継承関係があっても互換性がありません。Integer は Number のサブクラスですが、List<Integer> は List<Number> のサブタイプではないので、代入するとコンパイルエラーです。

Main.java
import java.util.ArrayList;import java.util.List;​public class Main {    public static void main(String[] args) {        List<Integer> ints = new ArrayList<>();        List<Number> nums = ints;        System.out.println(nums);    }}
ターミナル
javac Main.java

コンパイルエラー (7 行目): List<Integer> は List<Number> に代入できない

いろいろな型のリストを受け取りたいときは、ワイルドカードを使います。

・List<? extends Number>: Number かそのサブクラスのリスト。要素は Number として取り出せるが、null 以外は追加できない ・List<? super Integer>: Integer かそのスーパークラスのリスト。Integer を追加できるが、取り出した要素は Object としてしか扱えない ・List<?>: 何かの型のリスト。要素は Object として取り出せるだけ

Main.java
import java.util.ArrayList;import java.util.List;​public class Main {    static double sum(List<? extends Number> nums) {        double total = 0;        for (Number n : nums) {            total += n.doubleValue();        }        return total;    }​    static void addInts(List<? super Integer> dst) {        dst.add(1);        dst.add(2);    }​    public static void main(String[] args) {        List<Number> list = new ArrayList<>();        addInts(list);        list.add(2.5);        System.out.println(sum(list));        System.out.println(list);    }}
ターミナル
java Main
5.5
[1, 2, 2.5]

型パラメータには <T extends Comparable<T>> のように上限境界を付けられます。境界を付けると、メソッドの中で T の値に対して compareTo などの境界の型のメソッドを呼べます。

総称型の型引数はコンパイル後に消去されます (イレイジャ)。そのため、print(List<String>) と print(List<Integer>) のように型引数だけが違うメソッドは、実行時には同じ print(List) になってしまい、オーバーロードできません (コンパイルエラー)。

Comparator による並べ替え

Comparator.comparing(キーを取り出す関数) で、そのキーの昇順に並べる Comparator を作れます。reversed() で逆順にし、thenComparing でキーが同じときの次の基準を足せます。thenComparing の第 2 引数に Comparator を渡すと、2 つ目のキーだけを降順にすることもできます。

Main.java
import java.util.ArrayList;import java.util.Comparator;import java.util.List;​record Item(String name, int price) {}​public class Main {    public static void main(String[] args) {        List<Item> items = new ArrayList<>(List.of(            new Item("pen", 100), new Item("cup", 300), new Item("ink", 100)));        items.sort(Comparator.comparing(Item::price)            .thenComparing(Item::name, Comparator.reverseOrder()));        items.forEach(i -> System.out.println(i.name() + " " + i.price()));    }}
ターミナル
java Main
pen 100
ink 100
cup 300

null を含む要素を並べるときは、Comparator.nullsFirst(比較方法)・nullsLast(比較方法) で null の位置を決めます。

TreeSet や TreeMap に Comparator を渡すと、equals ではなく compare の結果が 0 になる要素を同じ要素とみなします。次のコードでは、長さで比べているので、cat と同じ長さの dog は追加されません。

Main.java
import java.util.Comparator;import java.util.List;import java.util.Set;import java.util.TreeSet;​public class Main {    public static void main(String[] args) {        Set<String> set = new TreeSet<>(Comparator.comparing(String::length));        set.addAll(List.of("cat", "dog", "bird", "ox"));        System.out.println(set);    }}
ターミナル
java Main
[ox, cat, bird]

コレクションの便利なメソッド

Java SE 8 以降、コレクションには処理を関数で渡すメソッドが追加されています。

・Map.merge(キー, 値, 関数): キーがなければ値を入れ、あれば既存の値と合成する。単語の出現回数を数えるのに便利 ・Map.computeIfAbsent(キー, 関数): キーがないときだけ、関数の結果を入れる ・Collection.removeIf(条件): 条件に合う要素をすべて削除する ・List.replaceAll(関数): 各要素を関数の結果に置き換える

Collections.unmodifiableList は、元のリストを変更できないように包んだビューを返します。ビュー自体は変更できませんが、元のリストを変更すると、その変更はビューからも見えます (コピーではないため)。

Main.java
import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.Map;import java.util.TreeMap;​public class Main {    public static void main(String[] args) {        Map<String, Integer> count = new TreeMap<>();        for (String w : "a b a c b a".split(" ")) {            count.merge(w, 1, Integer::sum);        }        System.out.println(count);​        List<Integer> nums = new ArrayList<>(List.of(1, 2, 3, 4, 5));        nums.removeIf(n -> n % 2 == 0);        nums.replaceAll(n -> n * 10);        System.out.println(nums);​        List<Integer> view = Collections.unmodifiableList(nums);        nums.add(70);        System.out.println(view);    }}
ターミナル
java Main
{a=3, b=2, c=1}
[10, 30, 50]
[10, 30, 50, 70]

試験でよくある引っかけ

  • Integer の == 比較

    -128 〜 127 の値はキャッシュされるので == が true になりますが、範囲外は false です。値の比較は equals を使います。

  • null のアンボクシング

    map.get(キー) + 1 は、キーがなく null が返ると NullPointerException です。

  • Deque の先頭と末尾

    push・pop は先頭、offer・add は末尾を操作します。1 つずつ状態を書いて追いましょう。

  • Arrays.asList と List.of

    Arrays.asList は set できるが add できない固定長、List.of は set もできません。

  • List<Integer> と List<Number>

    総称型は型引数が違えば互換性がありません。受け取るには List<? extends Number> を使います。

  • TreeSet の重複判定

    Comparator を渡した TreeSet は、compare が 0 の要素を重複とみなして追加しません。

問題で確認する

この分野の問題を、解説つきで読めます (登録不要)。

出典・参考

コード例は、試験の対象バージョンで実際にコンパイル・実行して結果を確認しています。