【Kotlin】レッスン4-6:コレクション×ジェネリクスを学ぼう|型安全なコードの基本を習得

一つ前のページではコレクション操作について学習しました。
今回は コレクションとジェネリクスの組み合わせ について見ていきましょう。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:関数編
Lesson4:コレクション編
・Lesson4-1:配列を理解しよう
・Lesson4-2:Listを理解しよう
・Lesson4-3:Setを理解しよう
・Lesson4-4:Mapを理解しよう
・Lesson4-5:コレクションを使いこなそう
・Lesson4-6:コレクションとジェネリクスを組み合わせよう ◁今回はココ
・確認問題4-☆1:ナインゲームを作ろう
・確認問題4-☆2:アラビア数字をローマ数字に変換しよう
・確認問題4-☆3:宝探しゲームを作ろう
Lesson5:オブジェクト指向編
コレクションとジェネリクスの組み合わせ|型を安全に制御する方法

コレクション(List、Set、Mapなど)はプログラムの中核を担いますが、型安全性を保ちながらこれらを効率よく扱うためにはジェネリクスの理解が重要です。
本記事ではコレクションとジェネリクスを組み合わせて使う方法を解説します。
ジュネリクスが何か分からない方は先に↓↓の記事で復習しましょう。

ジェネリクスの基本|Kotlinで型安全性を保つ書き方
ジェネリクス(Generics)とは、コードの再利用性や型安全性を高めるために導入された仕組みです。
コレクションとジェネリクスを組み合わせることで、特定の型だけを受け入れる安全なコレクションを作成できます。
これにより次のような利点が得られます:
- 型安全性の向上:不正な型の要素追加がコンパイル時に防止されます。
- コードの可読性向上:型情報が明示されることで、コードの意図が明確になります。
以下のコードのようにジェネリクスを用いて、コレクションを代入する変数に制限をかけます。
// 型を指定しない通常のリスト val list = listOf(1, "string", true) // あらゆる型が混在可能 // ジェネリクスを使った型安全なリスト val intList: List<Int> = listOf(1, 2, 3) // Int型のみに制限 val stringList: List<String> = listOf("Kotlin", "Java", "Python") // String型のみに制限 // stringListにInt型を追加しようとするとエラーになる // ジェネリクスを使ったセット・マップ val uniqueNumbers: Set<Int> = setOf(1, 2, 3, 1) // 重複要素は無視 val userMap: Map<Int, String> = mapOf(1 to "Alice", 2 to "Bob")
ジェネリクスを利用することで、開発者は意図しない型のデータが混入することを防ぎ、実行時エラーを回避できます。
まとめ|型安全なコレクションを扱おう
コレクションとジェネリクスを組み合わせることで、Kotlinのコードはより安全で読みやすくなります。
型の安全性を高めるジェネリクスはKotlinプログラミングにおいて重要な役割を果たしており、コレクションの操作と組み合わせることで、効率的かつエラーの少ないコードが実現します。
ぜひこの仕組みを活用してみてください!
練習問題|型安全なリスト・マップを作成しよう

コレクションとジェネリクスを活用して、型安全なリストやマップを作成するプログラムを作りましょう。
リストから条件に合う要素を抽出したり、マップからキーに対応する値を取得する操作を学びます。
また重複を許さない集合(Set)を使った例も含まれています。
この問題の要件
以下の要件に従ってコードを完成させてください。
- 型安全なリスト
numbers
を作成し、値として10, 20, 30, 40, 50
を格納すること。 - 型安全なマップ
userMap
を作成し、キーとして1, 2, 3
、値としてそれぞれ"佐藤"
,"田中"
,"鈴木"
を格納すること。 numbers
の中から偶数のみを抽出してリストに格納し、その内容を表示すること。userMap
からキー2
に対応する値を取得し、その内容を表示すること。- 型安全な集合
uniqueNumbers
を作成し、値として1, 2, 2, 3, 4, 4
を格納して表示すること。
ただし、以下のような実行結果となること。
数値リスト: [10, 20, 30, 40, 50] ユーザー一覧: {1=佐藤, 2=田中, 3=鈴木} 偶数リスト: [10, 20, 30, 40, 50] キー2のユーザー: 田中 ユニークな数値セット: [ 1, 2, 3, 4]
この問題を解くヒント
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
-
正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)1:main関数の定義
□ Listを用いた型安全なリストnumbersを定義し、初期化
□ printlnでリストの内容を出力
□ Mapを用いた型安全なマップuserMapを定義し、初期化
□ printlnでマップの内容を出力
□ Listのfilter関数を用いて偶数リストevenNumbersを作成
□ printlnで偶数リストを出力
□ Mapの検索機能を用いてキー2に対応する値を取得し、変数userNameに代入
□ if文でuserNameがnullでないかを判定
□ □ 真の場合、printlnで対応するユーザーを出力
□ □ else文
□ □ □ 該当ユーザーがいない場合にprintlnでメッセージを出力
□ Setを用いた型安全な集合uniqueNumbersを定義し、初期化
□ printlnでユニークな数値セットを出力
- ヒント2【穴埋め問題にする】
-
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
// メイン関数:プログラムのエントリポイント fun main() { // Listのジェネリクス例: 型安全なリストを作成 /*【穴埋め問題1】 ここでListを用いて型安全なリストnumbersを定義し、初期化するコードを書いてください。 */ println("数値リスト: $numbers") // Mapのジェネリクス例: キーと値の型を指定したマップ /*【穴埋め問題2】 ここでMapを用いて型安全なマップuserMapを定義し、初期化するコードを書いてください。 */ println("ユーザー一覧: $userMap") // フィルタリングの例 /*【穴埋め問題3】 ここでnumbersのfilter関数を用いて、偶数リストevenNumbersを作成するコードを書いてください。 */ println("偶数リスト: $evenNumbers") // Mapの検索例 /*【穴埋め問題4】 ここでuserMapからキー2に対応する値を取得し、変数userNameに代入するコードを書いてください。 */ if (userName != null) { println("キー2のユーザー: $userName") } else { println("該当するユーザーが見つかりません") } // Setのジェネリクス例: 重複を許さない型安全な集合 /*【穴埋め問題5】 ここでSetを用いて型安全な集合uniqueNumbersを定義し、初期化するコードを書いてください。 */ println("ユニークな数値セット: $uniqueNumbers") }
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
この問題の解答と解説
この問題の正解コードとその解説は以下の通りです。
クリックして開いて確認してください。
- 正解コード
-
// メイン関数:プログラムのエントリポイント fun main() { // Listのジェネリクス例: 型安全なリストを作成 val numbers: List<Int> = listOf(10, 20, 30, 40, 50) // Int型のリスト println("数値リスト: $numbers") // Mapのジェネリクス例: キーと値の型を指定したマップ val userMap: Map<Int, String> = mapOf(1 to "佐藤", 2 to "田中", 3 to "鈴木") // Intがキー、Stringが値 println("ユーザー一覧: $userMap") // フィルタリングの例 val evenNumbers = numbers.filter { it % 2 == 0 } // 偶数のみを抽出 println("偶数リスト: $evenNumbers") // Mapの検索例 val userName = userMap[ 2] // キー2の値を取得 if (userName != null) { println("キー2のユーザー: $userName") } else { println("該当するユーザーが見つかりません") } // Setのジェネリクス例: 重複を許さない型安全な集合 val uniqueNumbers: Set<Int> = setOf(1, 2, 2, 3, 4, 4) // 重複要素は自動的に削除 println("ユニークな数値セット: $uniqueNumbers") }
- 正解コードの解説
-
コードをブロックごとに分割して解説します解説します。
メイン関数の開始
fun main() { // メイン関数:プログラムのエントリーポイント }
fun main()
はプログラムの開始点です。Kotlinプログラムはここから実行されます。Listのジェネリクス例
val numbers: List<Int> = listOf(10, 20, 30, 40, 50) println("数値リスト: $numbers")
List<Int>
は整数型のリストを作成しています。ジェネリクス<Int>
によりリスト内に整数以外の値を含めることができなくなり、型安全性を確保できます。listOf
は不変(変更不可)なリストを作成するための関数です。
Mapのジェネリクス例
val userMap: Map<Int, String> = mapOf(1 to "佐藤", 2 to "田中", 3 to "鈴木") println("ユーザー一覧: $userMap")
Map<Int, String>
はキーが整数型、値が文字列型であるマップを作成します。mapOf
はキーと値のペアを指定してマップを作成する関数です。ここでは、1 to "佐藤"
のようにto
演算子でペアを作ります。
リストから条件に合う値を抽出
val evenNumbers = numbers.filter { it % 2 == 0 } println("偶数リスト: $evenNumbers")
filter
関数はリストの各要素を条件(ラムダ式)で評価し、条件を満たす要素のみを抽出します。{ it % 2 == 0 }
はリスト内の偶数を抽出する条件です。
Mapの値を検索
val userName = userMap[ 2] if (userName != null) { println("キー2のユーザー: $userName") } else { println("該当するユーザーが見つかりません") }
userMap[ 2]
はキー2
に対応する値(ここでは"田中"
)を取得します。- 値が存在しない場合は
null
が返されるため、if
文で確認しています。
Setのジェネリクス例
val uniqueNumbers: Set<Int> = setOf(1, 2, 2, 3, 4, 4) println("ユニークな数値セット: $uniqueNumbers")
Set<Int>
は重複を許さない集合です。ジェネリクスにより整数型だけを許可しています。setOf
は集合を作成する関数で、重複した値(ここでは2
と4
)は自動的に除外されます。
- サイト改善アンケート & ご指摘/ご質問
-
本サイトでは、みなさまの学習をよりサポートできるサービスを目指しております。
そのため、みなさまの「プログラミングを学習する理由」などを アンケート 形式でお伺いしています。また記事の内容に関する ご指摘 や ご質問 もお待ちしています。