9-3. 演習問題
問題1:選択問題
Section titled “問題1:選択問題”1-1. 次のコードの出力はどれか。
List<String> list = new ArrayList<>(List.of("c", "a", "b"));list.add("a");System.out.println(list.size());System.out.println(list.contains("a"));- A.
3とfalse - B.
4とtrue - C.
3とtrue - D. コンパイルエラー
解答と解説
正解:B
List は重複を許すため、"a" を追加しても既存の "a" は除去されない。size() は 4(c, a, b, a)になる。contains("a") は true。
Set なら重複を許さないため size() は 3 になる。コレクションを選ぶ際は重複を許すかどうかが重要な判断基準だ。
1-2. HashMap の特性として正しいものはどれか。
- A. キーの順序が挿入順に保証される
- B. キーが重複した場合、古い値が保持される
- C. null をキーや値として使用できる
- D. スレッドセーフである
解答と解説
正解:C
- A:
HashMapの順序は保証されない。挿入順を保持したいならLinkedHashMapを使う - B:キーが重複した場合、新しい値で上書きされる。
put("key", "old")→put("key", "new")→ 値は"new" - C:正しい。
HashMapはnullキーを1つだけ、null値は複数持てる(Hashtableと異なる点) - D:
HashMapはスレッドセーフではない。マルチスレッド環境ではConcurrentHashMapを使う
1-3. 次のStream APIのコードで result に格納される値はどれか。
List<Integer> nums = List.of(1, 2, 3, 4, 5);int result = nums.stream() .filter(n -> n % 2 != 0) .mapToInt(Integer::intValue) .sum();- A.
6(偶数の合計) - B.
9(奇数の合計) - C.
15(全合計) - D.
3(奇数の個数)
解答と解説
正解:B
処理を順に追う:
filter(n -> n % 2 != 0):奇数のみ →[1, 3, 5]mapToInt(Integer::intValue):IntStream(プリミティブのストリーム)に変換.sum():合計 →1 + 3 + 5 = 9
mapToInt は Map<Integer> ではなく IntStream を返すため、sum()・average()・min()・max() などのプリミティブ向け終端操作が使える。
1-4. ラムダ式 (a, b) -> a.compareTo(b) と同じ意味のメソッド参照はどれか。
- A.
String::compareTo - B.
Comparator::compare - C.
String::compareToIgnoreCase - D.
Comparator.naturalOrder()
解答と解説
正解:A
(a, b) -> a.compareTo(b) は String の compareTo メソッドを a(第1引数)のインスタンスに対して呼んでいる。これはインスタンスメソッド参照で String::compareTo と書ける。
実務でのソート:
List<String> list = new ArrayList<>(List.of("banana", "apple", "cherry"));
list.sort((a, b) -> a.compareTo(b)); // ラムダ式list.sort(String::compareTo); // メソッド参照(同じ意味)list.sort(Comparator.naturalOrder()); // 標準的な自然順序list.sort(Comparator.reverseOrder()); // 逆順問題2:穴埋め問題
Section titled “問題2:穴埋め問題”2. 次のコードの( )に入るコードを答えよ。
List<String> names = List.of("Alice", "Bob", "Charlie", "Diana");
// (1) 名前の長さが5以上のものだけを取り出すList<String> longNames = names.(1)() .filter(s -> s.(2)() >= 5) .collect(Collectors.toList());// ["Alice", "Charlie", "Diana"]
// (2) 全ての名前を大文字に変換してリスト化List<String> upper = names.stream() .map(String::(3)) .collect(Collectors.toList());
// (3) 名前の文字数の合計int total = names.stream() .(4)ToInt(String::length) .sum();解答と解説
streamlengthtoUpperCasemap
解説
(1) コレクションをStreamに変換するには .stream() を呼ぶ。
(2) String.length() で文字数を取得する。
(3) String::toUpperCase はメソッド参照。s -> s.toUpperCase() と同じ意味。
(4) mapToInt で Stream<String> から IntStream に変換し、.sum() で合計できる。map だと Stream<Integer> になるため .sum() が使えない。
問題3:記述問題
Section titled “問題3:記述問題”3-1. for ループと Stream API を使った書き方の違いを、可読性・副作用・再利用性の観点で比較せよ。
解答と解説
for ループ(命令型スタイル)
List<Integer> result = new ArrayList<>();for (Integer n : numbers) { if (n % 2 == 0) { result.add(n * n); }}Stream API(宣言型スタイル)
List<Integer> result = numbers.stream() .filter(n -> n % 2 == 0) .map(n -> n * n) .collect(Collectors.toList());| 観点 | for ループ | Stream API |
|---|---|---|
| 可読性 | 処理の手順が細かく書かれる | 「何をするか」が簡潔に表現される |
| 副作用 | 外部の変数(result)を変更する | 元のコレクションを変更しない(非破壊的) |
| 再利用性 | ループを使い捨てで書くことが多い | .filter() の条件等を変数にして再利用しやすい |
| デバッグ | ステップ実行しやすい | 中間状態の確認は .peek() を使う |
実務では Stream API が好まれる場面が多いが、複雑なロジックや早期リターンが必要な場合は for ループの方がシンプルになることもある。
3-2. 次のコードを Stream API を使って書き直せ。
List<String> result = new ArrayList<>();for (Book book : books) { if (book.genre().equals("tech") && book.price() >= 3000) { result.add(book.title().toUpperCase()); }}Collections.sort(result);Book は record Book(String title, String author, int price, String genre) {} とする。
解答と解説
List<String> result = books.stream() .filter(b -> b.genre().equals("tech") && b.price() >= 3000) .map(b -> b.title().toUpperCase()) .sorted() .collect(Collectors.toList());ポイント:
filterの条件は&&で複数組み合わせられるmapで変換と同時にtoUpperCase()を適用sorted()でソートをStreamの中に組み込める(Collections.sort()不要)- 元の
booksリストは変更されない(非破壊的)
問題4:ハンズオン
Section titled “問題4:ハンズオン”下の Java WASM プレイグラウンドで List・Stream API・Collectors.partitioningBy() を使った集計を実装せよ。
取り組む内容
Section titled “取り組む内容”- 平均点が80以上の生徒名一覧をソート付きで出力する
- 全生徒の合計点平均を
mapToIntとaverage()で求める - 数学最高点の生徒を
maxで求める partitioningBy()で「80以上 / 80未満」に分けた Map を作って出力する
確認したいポイント
Section titled “確認したいポイント”mapToIntを使うと、なぜaverage()やsum()が自然に書けるかsorted()とComparator.comparingInt()の役割の違いpartitioningBy()がMap<Boolean, List<T>>を返す意味