GPT-5 miniに聞き学ぶ、オブジェクト指向の実用機能ジェネリクスとコレクション:AIアシスト時代のJavaプログラミング入門(7)
対話型AI(人工知能)にアドバイスを受けながら進めるJavaプログラミングの入門連載。引き続き、オブジェクト指向プログラミングの機能である、ジェネリクスとコレクションを学習します。特定のデータ型に依存しないクラスの考え方、それを利用したユーティリティーであるコレクションを理解しましょう。
本連載のサンプルコードをGitHubで公開しています。こちらからダウンロードしてみてください。
目次
オブジェクト指向の実用的な用途
対話型AI(人工知能)にアドバイスを受けながら進めるJavaプログラミングの入門連載「AIアシスト時代のJavaプログラミング入門」。前回までで、Javaをオブジェクト指向言語たらしめる機能を一通り学びました。しかしながら、「あくまでも例なのは分かるが、犬とか猫とか動物とかではなく、もっと実用的な用途を知りたい。」と考える方もいるのではないでしょうか? そこで今回からは、オブジェクト指向の延長として、実用的な用途に踏み込んでいきます。
【補足】GPT-5 miniとGrok Code Fast 1
Visual Studio Code(以降、VS Code)バージョン1.103において、OpenAIの新しいAIモデルGPT-5が利用可能になりました。プレミアムリクエストを消費しないGPT-5 miniも利用可能なので、今回からこのモデルを使っていきます。なお、初めてGPT-5 miniを選択すると、図1のようにGPT-5 miniを有効にするかどうか聞かれるので、[Enable]をクリックして有効にしてください。
なお、xAIによるGrok Code Fast 1も同様に利用可能です。有効化が必要な点も同じですので、興味のある人は試してみるとよいでしょう。
VS CodeからGitHub Copilot(以降、Copilot)に、新たに「Javaのオブジェクト指向機能を使った実用的な機能を知りたい。コードは不要です。」と投げてみました(図2)。
カプセル化、継承、ポリモーフィズム、抽象化といった、これまでに学習した内容に加えて、はじめて目にするキーワードが追加でたくさん登場しました。改めて、Javaのオブジェクト指向の奥深さがうかがい知れますね。中には技法的なものも混じっているのですが、今回は7番目の「ジェネリクス(型安全な再利用)」をピックアップします。
ジェネリクス(Generics)
「ジェネリクス」とは、「一般的な」「総括的な」という意味です。「ポリモーフィズム」同様に日常生活にあまり登場しませんが、「ジェネリック医薬品」など目にすることがありますね。図2の回答を見ると、以下のように説明されています。
・コレクションやユーティリティーを型安全に再利用。APIの誤用をコンパイル時に検出。
「再利用」は、一貫してオブジェクト指向のメリットとしてのキーワードなのでひとまず置いておき、ここでは「型安全」と「コレクション」「ユーティリティー」に注目した方がよさそうです。「API」とはApplication Program Interfaceの略ですが、ここではメソッドのことと思っておいて構いません。
【補足】記載ルールについて
今回も前回と同様に、AIの回答と@ITの記載ルールが異なる場合、本文中では@ITのルールを優先しています。
コレクションとは
コレクション(Collection)という用語自体は、第4回で拡張for文を扱う際にちらっと登場しました。とすると、配列と共通点がありそうです。そこで、まずはコレクションについて聞いてみましょう。「コレクションの目的を説明して。初心者でも分かるように専門用語はできるだけ控えて簡潔にコードなしで。」と投げてみました(図3)。
【補足】GPT-5 miniへの注文は細かく
今回使用しているGPT-5 miniは、前回まで使ってきたGPT-4oと比較すると、より詳細に網羅的に、という傾向があるようです。そのため、ざっくりした質問(プロンプト)では回答量が多く専門用語も多出して入門者には難しいと判断し、本稿での質問は注文を多くして回答を絞ることにしました。
「コレクションとは」に示されている内容が、コレクションの目的をひとことで表しています。
複数のデータ(値や物の情報)を一かたまりで扱うための仕組み。箱やリストのように、たくさんのものをまとめて管理するために使う
コレクションの名の通り、複数のデータをかたまりで扱うための機能、ということです。ますます配列のようなものということになりますね。ただし「目的」を見ていくと、「データをまとめて保存する」のように配列に共通する機能の他に、「追加・削除・取り出しが簡単にできる」とあるように、配列にはない機能を持っていそうです。配列は要素数が固定で、追加や削除といった操作はありませんでした。
「例え」を見ると、買い物リストや住所録への応用が考えられるとあります。なかなか便利そうで実用的な機能がコレクションというわけです(図4)。
コレクションにはどのような種類があるのかも聞いてみました。全部を列挙されると困りそうなので、「代表的なコレクションを用途別に一文で説明しながら列挙して。」とよく使いそうなものだけを挙げてもらうことにしました(図5)。
それでも9個も挙げてくれましたが、先頭に近いものがよく使うものと思ってよさそうです。ListとArrayListの関係など、どのように使うのかは、後ほど具体的なコードとして見ていくことにしましょう。
- List(例:ArrayList):順番を保って同じ値を何度でも入れられ、位置や順序で扱いたいときに使う
- Set(例:HashSet):同じ要素を重複させたくないときに使う
- Map(例:HashMap):キーと値の組でデータを保存し、キーで素早く値を取り出したいときに使う
コレクションとジェネリクスの関係
コレクションの姿が見えてきましたが、ジェネリクスとの関連は? という点について、さらなる質問で聞いてみましょう。「コレクションとジェネリクスの関係を説明して。初心者でも分かるように専門用語はできるだけ控えて簡潔にコードなしで。」と投げてみました(図6)。
「概要(簡潔)」の2行目に書かれている内容が、ジェネリクスの機能を一つ、端的に表しています。
ジェネリクスは「そのコレクションが何の種類のものを入れるかをあらかじめ決める仕組み」。
配列には、それが何の配列かを表すint[]などの型がありましたが、それに相当するものがジェネリクスということのようです。「関係(初心者向け)」の1行目に「コレクションに入るものの種類を明確にできる(例:文字列だけ、数値だけ)」とあるので、同じように文字列(String)、数値(intなど)を指定できるということですね。2行目以降では、メリットとして安全性や再利用性について書かれているので、これらについては後ほどコードを見ながら明らかにしていきましょう。
「たとえ」に書かれている、以下が分かりやすいです(図7)。
「リンゴだけ入る箱」を用意しておくと、間違えてナシを入れられないし、中身を取り出すときにリンゴだと安心して扱える、というイメージ。
コレクションを使うコード
このへんで、具体的なコードを示してもらい、コレクションを通じたジェネリクスの利用イメージを深めていくことにしましょう。使うコレクションは、最初に出てきたArrayListにします。ここからはVS CodeのAgentモードを活用して、「basicプロジェクトからgenericsプロジェクトを作り、ArrayListの簡単なサンプルコードを入れて。」と投げて一連の作業を実行してもらいました。プロジェクトが作成され、App.javaファイルにサンプルコードが生成されます。
注目すべきはApp.javaです。開いて内容を確認してもよいですが、コードを基に説明してもらうことにします。「生成されたApp.javaのコードを、専門用語を使って説明して。コードの説明以外は不要です。」と投げてみました。これまでが割とふんわりした回答を期待していたのに対し、ここからは具体的に用語を使ってくれることを期待します。ただ、GPT-5 miniの傾向から、補足的な説明を加えてくると思われるので、ひとまずはコードに絞って解説してもらいます(図9)。
やや長いですが、処理単位ごとに箇条書きで要点が列挙されます。これを読むと、コードのどの部分で何をやっているか分かりますね。これを踏み台に、対応するコードも見ていくことにしましょう(図10)。
以下、図10の赤字を補足する形で、図9の回答も使いながらコードを説明します。mainメソッドやprintlnメソッドなど既出の内容は省きます。
・import文
java.util.Listとjava.util.ArrayListについて簡単に説明してくれています。Listがインタフェース、ArrayListが実装クラスというわけです。このへんは前回で学習した内容ですね。java.util.Listといった形式やimport文って何? という疑問が湧くと思いますが、後続の回のテーマにもなっているので、詳しくはそちらで説明します。ここではListとArrayListを使うための文、と理解しておけば十分です。
・ジェネリクスによる型指定(List<String> names = new ArrayList<>();)
コレクションはクラスなので、newによってインスタンス化するのはこれまで同様です。ここには、重要なキーワードが登場しています。List<String>が「ジェネリック型」で、<...>の中のStringは「型パラメーター」というようです。ジェネリクスを使った型だからジェネリック型、ジェネリック型が扱う型を指定するから型パラメーターというわけですね。ジェネリック型では、「<>」で扱う型を指定します。
重要なのは、型パラメーターで指定するString以外の値は入らない、これで型安全が保証されているということです。また、ArrayList<>の型パラメーターは空っぽですが、これはList<String>から自明なので、第2回で学習した「型の推論」が働いています。「<>」は、その見た目から「ダイヤモンド演算子」と呼ばれます。
・要素の追加(names.add("Alice"); 等)
・型チェックの例示コメント(names.add(123); // コンパイルエラー)
自明なのか触れられていませんが、コレクションはインスタンス化した時点では要素の数はゼロ、すなわち空です。であるので、要素は追加していく必要があります。これに使うのがaddメソッドです。上記のように、型パラメーターで指定するString以外の値は入らないので、数値型である「123」を入れようとするとコンパイルエラーとなります。ソースコードの段階で、型の間違いを防いでくれるというわけです。
・要素数取得と反復(names.size()と拡張forループ)
・要素取得(names.get(0))
コレクションでは、配列と同様に拡張for文で全要素を走査できます。これも配列と同様にインデックスで要素にアクセスできます(getメソッドを利用)。配列と異なり、要素の数は変動するので、要素数を取得する手段がsizeメソッドとして用意されています。
ジェネリック型の定義
ここまではArrayListというジェネリック型を利用するコードを見てきましたが、オブジェクト指向の学習的には、どのように定義するのかも知りたいところです。そこで、「ArrayListの定義のコードを大ざっぱに知りたい。」と投げてみました。コードが長めに提示されるので、説明部分を切り取ったのが図11です。
「ポイント(短く)」にはいろいろ説明がありますが、それも踏まえてコードに説明を加えてみたのが図12です。全部を説明し切れないので、クラスそのものの定義やコンストラクタ、登場済みのaddやgetなどのメソッドに絞っています。
注目したいのは、クラス定義に型パラメーターを指定していることです。これにより、クラスがジェネリック型になるわけです。ここで、型パラメーターは「<E>」となっており、これはクラス定義中で使う仮の型です。実際の型は利用時に指定されますが、定義時には実際の型は分からないので、このように仮の名前としておくわけです。実際、addメソッドやgetメソッドでは、引数と戻り値の型はEとなっています。
このように、実際にどのような型で使われるか? ということと関係なくクラスを定義できるので、型ごとにクラスを定義する必要がなくなります。ジェネリクスの再利用性とは、ここから来ているのが分かりますね(図13)。
こんな質問をしてみたい!
ここでは、コレクションを題材にジェネリクスについて学習してきました。実は、ジェネリクスはクラスに限ったものではありません。ジェネリクスのクラス以外の適用について聞いてみると、ジェネリクスの理解の幅が広がるかもしれませんよ!
その他のコレクション
ジェネリクスとはどういうものか、コレクションがジェネリクスをどのように利用するかを見てきました。既に、コレクションの一つであるList(ArrayList)については簡単な利用コードを見てきましたが、ここで他のコレクションにも注目してみましょう。これらのコレクションはジェネリック型なので、サンプルで示された型以外にも使えるということを押さえておきましょう。
Set(HashSet)
改めてList(ArrayList)について振り返ってみると、「順番を保って同じ値を何度でも入れられ、位置や順序で扱いたいときに使う」コレクションでした。つまり、配列的なものがListであるというわけです。Set(HashSet)はどうでしょうか? 「同じ要素を重複させたくないときに使う」とあるので、役割はListと異なりそうです。
これを確かめるために、「basicプロジェクトからcollectionプロジェクトを作り、HashSetの簡単なサンプルコードを入れて。」と投げて一連の作業を実行してもらいました。プロジェクトが作成され、App.javaファイルにサンプルコードが生成されます。作成途中で、サンプルの要点が既に示されているので、これをあらかじめ抜粋しておきます(図14)。
これを踏まえて、コードに説明を入れてみたのが図15です。
SetインタフェースとhashSetクラスの関係など、Listと構造は同じであり、インスタンスの生成についても同様です。また、addメソッドで要素を追加するのも同じですが、異なるのは重複を許さない(重複する追加は無視される)ことです。これが、Setの性質である「要素を重複させない」に通じるのですね。
この他、sizeメソッド、containsメソッド、拡張for文、removeメソッドの例が示されていますが、これらはListと同じです。異なるのは、拡張for文では順序が保証されないということです。つまり、入れた順に出てくるというわけではないということですね。これは、順序を保証するListとの大きな違いとなるので覚えておきましょう。
なお、回答では特に触れられていませんでしたが、Listのgetメソッドのように要素を個別で取り出すことはできません。順序がないので、場所の指定のしようがないためですね。その代わり、containsメソッドで存在は確認できるので、それをもって取り出すといった操作と見なすこともできるでしょう。
【補足】Hashとは
HashSetと、次で紹介するHashMapは、Hash(ハッシュ)という仕組みで要素の場所を管理しています。ハッシュとは、ある値によって一意に定まる計算方法およびその結果のことで、値が異なればハッシュも異なるという性質を持っています。これらのコレクションでは、このハッシュを利用して要素への高速なアクセスを実現しています。
Map(HashMap)
お次はMap(HashMap)はどうでしょうか。「キーと値の組でデータを保存し、キーで素早く値を取り出したいときに使う」とあります。値とは別に「キー」が登場しているので、これが重要な役割を果たしそうです。これを確かめるために、「collectionプロジェクトにHashMapの簡単なサンプルコードを追加して、要点もお願い。」と投げてサンプルコードを追加してもらいました。既存のApp.javaファイルにサンプルコードが追加されます。作成途中で、サンプルの要点が既に示されているので、これをあらかじめ抜粋しておきます(図16)。
これを踏まえて、コードに説明を入れてみたのが図17です。
こちらもHashSetのサンプルと似ていますが、幾つか違うところがありますね。
一つは、インスタンス生成時の型パラメーターが、<String, Integer>と2つあることです。SimpleArrsyListでは要素の型だけが必要なので型パラメーターは1つだけでしたが、HashMapのようにキーと値の型が必要な場合には型パラメーターは2つになるわけですね。最初のStringがキーの型に、Integerが値の型に相当します。
もう一つは、要素の追加にはaddメソッドでなくputメソッドを使う点です。このとき、最初の引数にはキーを、2番目の引数には値を指定しています。特に示されていませんでしたが、同じキーでputメソッドを呼び出すと、同じキーの値ができるわけではなく値が書き換えられます。このへんの振る舞いはSetに似ていますね。
値の取り出しはgetメソッドで、キーのみを指定します。containsメソッドでキーの存在を確認することもできますね。なお、拡張for文による要素の取り出しは、少し変わった形式になります。Mapでは要素をキーと値のペアで扱うので、それを受け取るためにEntryという特別なクラスを使います。Entryクラスのインスタンスからは、getKeyメソッド、getValueメソッドで、キーと値をそれぞれ取り出せます。
最後に、リスト、セット、マップの特徴をまとめてみたのが図18です。
こんな質問をしてみたい!
ここでは、SetとHashSet、MapとHashMapについてコードを通じてその動きを学習しました。ArrayListも含めて、コレクションには他にもいろいろな実装があるようです。ArrayList、HashSet、HashMap以外のコレクションについて聞いてみると、コレクションに求められる機能や性能の違いが分かり、コレクションひいてはジェネリクスの理解の幅が広がるかもしれませんよ!
まとめ
今回は、オブジェクト指向プログラミングの実用的な例として、ジェネリクスとコレクションをAIに聞きながら学習しました。
次回は、まだまだ知らないオブジェクト指向の機能として、列挙体とレコード型を学習します。
筆者紹介
WINGSプロジェクト 山内直
WINGSプロジェクト所属のテクニカルライター。出版社秀和システムを経てフリーランスとして独立。ライター、編集者、開発者、講師業に従事。屋号は「たまデジ。」。
・たまデジ。 | たまプラーザで生活、仕事する。(https://naosan.jp/)
WINGSプロジェクト
有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティー(代表山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手掛ける。2021年10月時点での登録メンバーは55人で、現在も執筆メンバーを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。
・サーバーサイド技術の学び舎 - WINGS(https://wings.msn.to/)
・RSS(https://wings.msn.to/contents/rss.php)
・X: @WingsPro_info(https://x.com/WingsPro_info)
・Facebook(https://www.facebook.com/WINGSProject)
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
プログラマー以外にもおすすめ 「Visual Studio Code」のインストールから基本設定まで
プログラミング用としては、利用者が多いコードエディタの「Visual Studio Code」。拡張機能が豊富で、エンドユーザーや管理者であっても、高機能なテキストエディタとして活用できるものとなっている。特に最近では、ツール類の設定ファイルがJSON形式やXML形式になっている。これらを編集する際にも、Visual Studio Codeは便利だ。
Visual Studio Codeを活用するための人気TIPS 12選
人気過去連載を電子書籍化して無料ダウンロード提供する@IT eBookシリーズ。第52弾は、Microsoftが無償で提供するソースコードエディタ「Visual Studio Code」。高機能なこのエディタを使いやすくするTIPS集から12本をまとめてお送りする。
初心者向け、データ分析・AI・機械学習の勉強方法 Deep Insiderで学ぼう
データ分析、AI/機械学習の実装、生成AIの活用(まとめてデータサイエンス)は、もはや多くの人に必要な知識となっています。これらの基礎はどうやって学べばよいのでしょうか? オススメの勉強方法を紹介します。

















