はじめに
この章では、java.utilパッケージをimportして利用できる便利なクラスを学んで行きます。
java.utilパッケージには、配列操作、イベント・モデル、日付および時間など、さまざまな基本的かつ便利かつ現場で使いまくりの機能があります。
このような「便利な機能を提供する仕組み」を総じて「フレームワーク」と読びます。
コレクション(複数要素の集まり) +フレームワーク (便利な機能を提供する仕組み) ということです!
この章では、その中でも、 配列操作に着目して学んでいきましょう!
Step1: 順序を持ったコレクション 【List】
配列を操作する便利なクラスを紹介します!
ArrayListクラスとLinkedListクラスです。
配列の操作とは言いましたが、 少し前にやった配列とは少々異なります。
配列は、最初にサイズを決めるため、後からサイズを拡張することはできません。
しかし、 Listクラスは要素を追加した分だけ自動的にサイズが拡張される動的な配列を作ることができます。
また、Listクラスの様々なメソッドを使うことにより値を追加したり途中に挿入したり、削除することも可能です。
定義方法
補足
Java1.7以降では、 <> ダイヤモンド演算子)を用いて以下のように記述することが可能です。
・仮型引数による型の保証
左辺の型が明記されている場合は、 ArrayList が持つジェネリクスという機能が働きます。
ArrayListの型を仮の型引数とし、 Listで指定された型を実際の型としてコンパイルします。
(※ジェネリクスについては紹介程度しておきます。
ArrayListクラス / LinkedListの使用例
生成したArrayListクラスのインスタンスを、 Listインタフェース型の変数sampleListに保持しています。
Listインタフェースでは、要素の追加は addメソッドで行います。
また、パターン1と2は意味合いとして同じになります。値を取り出すときはgetメソッドを使用します。
List系クラスの特徴と使い分け
ArrayListクラスは配列でリストを実装しており、「添え字による要素へのアクセス」 が高速です。
要素の 「追加」 に関しても、 新たな要素を末尾へ加えるだけなので問題なく行うことができます。
しかし、配列の途中の位置への要素の 「挿入」 や 「削除」に関しては挿入・削除した位置以降の 全ての要素の位置を移動させるという処理を行う必要があるため低速です。
LinkedListクラスはリスト構造を使用して実装しています。
このため、「添え字による要素へのアクセス」は、毎回先頭から順番に要素をたどっていきながら 目的の位置を探す (添え字の番号まで移動していく) 必要があるため、低速です。
各クラスの特徴を踏まえて、 用途に応じてクラスを選択することが Listインタフェースを使いこなすポイントとなります。
単純に「動的にサイズが拡張される配列」としてコレクションを使用したい ArrayListクラス
要素数が多くて、且つ要素の挿入・削除を頻繁に行うことが予想 LinkedListクラス
Step2: キーと値とのマッピングを保持するコレクション【Map】
Listと似たようなもので、連想配列を取り扱うものに Map というコレクションがあります。
Mapは二つの要素から成ります。
一つ目は「キー」と呼ばれる値です。
二つ目は「値」になります。
「キー」は簡単にいえば、 値につける名前だと思ってもらえば大丈夫です。
値ひとつひとつに「キー」 が存在しており、「キー」と「値」がペアになっているのがMapの特徴です。
Map系クラスの特徴
それぞれに特徴がありますので簡単に見ていきましょう。
定義方法
こちらもArrayList等と同様の記述となります。 (※ダイヤモンド演算子を用いての記述も可能です。)
Map系クラスの使用例
【出力結果】
生成したHashMapクラスのインスタンスをMapインタフェース型の変数sampleHashMapに保持しています。
Listインタフェースでは、要素の追加はaddメソッドを使用しましたが、Mapインタフェースにはaddというメソッドは存在しません。
その代わりに put という名前のメソッドで要素の追加を行います。
putメソッドには引数を2つ指定します。第1引数がキー、第2引数がキーに紐づく値です。
値を取り出すときは、getメソッドを使用します。
補足
- get()の引数は Object
Object を引数に取るため、あらゆる型やクラスのキーに対応可能です。
(※Objectについては後述します。)
しかし、HashMap の変数を定義した際のキー値と一致しないキー値が指定された場合は、
エラーにはならないものの、ワーニングが表示されます。 - Object クラス
Object はクラスとして定義されており、全ての型やクラスの親です。
継承については学びましたが、 実は、すべてのクラスは Objectクラスから成り立っています。
そのため、Object で定義された型 (クラス)の変数や、メソッドの引数はあらゆる値を格納することができます。)
【サンプル: getに指定する引数】
上記のmap.get("1");は指定は可能ですが、 ワーニングが表示され変数定義時にマッピングしたキー値の型と不一致であるため、 取得結果がnull となります。
Step3: 重複要素のないコレクション 【Set】
この他に全く新しく登場してきたのが、 Set インタフェースを実装するHashSetクラスやTreeSetクラスです。
値の格納方法は、ListやMapの格納方法の中間のような形式です。
Setは、Mapのようなキーと値の関連付けを行わずListのように値だけを格納しますが、インデックスを使って格納されているわけではありません。
また、重複して同じ値を格納することもできません。
定義方法
こちらもList、Map等と同様の記述となります。 (※ダイヤモンド演算子を用いての記述も可能です。)
Set系クラスの例
HashSet TreeSet LinkedHashSet の例がありますので、下記を作成してご自身のPCで試してみてください!
【出力結果】
このようにして、配列の並びを操ることができます。
では、いつ使用すれば良いのか。
例えばスーパーのシステムを作っていて、経営者から「うちの商品を安い順からリストアップしたい」とお願いされたとします。
「どうしたものか… 項目を整理してくれるものはないだろうか… そうだ! TreeSet を使ってみよう」
となるわけですね。
拡張for文
例題の中に見慣れないfor文があったかと思います。
これを、 拡張for文と呼びます。
これまで学んできたfor文との差は、要素の指定ができないということです。
上記のようにすれば要素の指定ができるわけですが、リストの何番目が必要という要件がなければ拡張for文を活用することが多いです。
拡張for文は、記述内容がシンプルでコーディングもしやすく、可読性も優れているので現場では重宝されます。
特に、通常のfor文と違い記述ミスが軽減される点で、 通常のfor文よりも需要は大きいです。
オマケ
Mapの要素を取得する場合には、いくつか特別な書き方がありますので簡単に紹介します。
(以下はMap系クラスの使用例の続きとします)
【出力結果】
•entrySet()
Setと、Mapの応用です。
Mapのエントリー (キーと値) を型としたSetコレクションになり、戻り値はSet<Map. Entry<K,V>>と定義されています。
上記のように拡張for文と併せて記述することで、sampleHashMapが保持する要素をリストのように扱うことが可能となります!
またkeySet() も同様ですが、sampleHashMap が保持する要素のキー値のみを返しますので、受け皿はStringクラスとなります。
コレクションは機能が豊富で覚えることが多いですが、現場では一番使用率が高いと言っても過言ではありません!
是非使いこなせるようになりましょう!
課題
Java中級からはEclipseでの課題対応となります。
2-10のフォルダの中にプロジェクトがありますので、インポートして以下の画像のように出力されるようにコーディングしなさい。
