[Kotlin]Map / MutableMapの特徴と使い方

今回はKotlinのMapです。JavaScriptやPHPなら連想配列、Pythonなら辞書という呼び名で馴染みがある方も多いかも知れません。そんなMapの基本をお伝えしようと思います。

Mapの特徴

まずはMapがどういったものなのか、その特徴を挙げてみます。

  1. 値をキー(Key)とバリュー(Value)のペアで管理する
  2. キーはユニーク(ただ1つ)である必要があるが、バリューは重複可
  3. 値のアクセスにはインデックス番号ではなくキーを指定する

つまるところ、Mapの特徴といえば「キーとバリューでの値管理」に尽きます。

Listの場合、自動的に番号が付けられた箱に値が入っている構造なのに対し、

Mapは箱自体に名前を付けて管理するイメージです。この箱に付けられた名前がキーとなります。

Mapの作成

MapもListやSetと同じようにOf関数で作成しますが、その引数は他のコレクションとは若干違いがあります。

val map = mapOf("とりあえず" to "ビール",
                "3杯目" to "ハイボール",
                "締め" to "ワイン")
println(map)
//{とりあえず=ビール, 3杯目=ハイボール, 締め=ワイン}

ここではリードオンリーのMap型のインスタンスを作成しています。

Mapのインスタンスを作成する際、値を代入するには(key to value,key to value)のように、 キーとバリューを「to」でつなぎ、いくつものキー、バリューペアを同時に代入していく方法をとります。

Mapの中身はPair型

同じような形で値を代入する型にPair型があります。

ここでは詳しくは取り上げませんが、2つの値をまとめて1つの変数に代入できる、Pair型という型があるということは、覚えておいて損はありません。

型パラメータを明示してPair型のインスタンスを作成してみます。

val month: Pair<Int,String> = 1 to "January"

もしくはPairクラスのコンストラクタで、

val month = Pair(1,"January")

これでも同じ結果となります。

ここでMapの型パラメータを覗いてみると、

んーそっくり。つまりMapの内部構造はPair型のListとも言えるわけです。

このPair型、面白いのは1つのインスタンスから、2つの変数に同時に値を代入できるというところでしょう。

val (x,y) = month

この場合Pair型の最初の値である1がxに、次の"January"がyにそれぞれ代入されます。

Mapでもこのような挙動を扱うことが多いので、若干蛇足ではあるかも知れませんがご紹介しておきました。

値へのアクセス

Mapでは他のコレクションと違い、インデックス番号ではなく、キーによってバリューにアクセスします。

println(map["とりあえず"])     //ビール

ただし、バリューでキーを呼び出すことはできません。

println(map["ビール"])     //null

"ビール"というキーは無いので、返答はnullとなります。

全ての要素を出力するプロパティ

keys、valuesプロパティで全てのキー、バリューを出力できます。要素数はお馴染みのsizeプロパティです。

println(map.keys)     //[とりあえず, 3杯目, 締め]
println(map.values)     //[ビール, ハイボール, ワイン]
println(map.size)     //3

MutableMap

他のコレクションと同様、Mapにもリードオンリーと変更可能の2種類があります。変更可能のMapを作成してみましょう。

val mMap = mutableMapOf<Int,String>()

値無しで作成することももちろん可能ですが、その場合は型パラメータを明示しておきます。

値の追加

このMutableMapに値を追加するには複数の方法があります。

mMap[1] = "枝豆"
mMap.put(2,"唐揚げ")
mMap += 3 to "牛とろとろ煮"
println(mMap)
//{1=枝豆, 2=唐揚げ, 3=牛とろとろ煮}

1行目ではキーをインデックスのように扱い、=の左辺でキー、右辺でバリューを登録しています。

2行目のように、putメソッドでキーとバリューを追加することも可能です。ただIntelliJではputメソッドによる追加は推奨されるものでは無いらしく、使用には問題ありませんが警告が出ます。

3行目では+=演算子で追加しています。この場合は新規作成したときと同じように、キーとバリューをtoでつなげて登録しましょう。

どの方法でも既に同じキーが存在している場合、そのバリューを上書きします。

複数のキー、バリューペアを追加する

上記の+=演算子や、putAllメソッドを使用することで、複数のペアをMapに追加することができます。

mMap += mapOf(1 to "枝豆",
            2 to "唐揚げ",
            3 to "牛とろとろ煮")
mMap.putAll(listOf(4 to "サラダ",
                5 to "揚げ出し"))

下のputAllではListを追加していることに注目してみてください。

複数の値を追加する場合、追加する型はMapでもListでもかまいません。Listを選択した場合、追加する型はList<Pair<Int,String>>となります。

値の削除

値を削除するにはremoveメソッドを使用します。

mMap.remove(1)
mMap.remove(2,"唐揚げ")
println(mMap)
//{3=牛とろとろ煮}

キーだけを指定しても、キーとバリュー両方指定してもかまいません。

両方指定した場合、バリューの指定が実際と違っていれば、そのremoveは無視されます。

全要素の削除

Mapの全ての要素を削除する場合はclearメソッドを使用します。

mMap.clear()

これも他のコレクション同様、引数無しのメソッドです。Mutable〇〇にしか使えませんので注意しましょう。

Mapのループ処理

最後にループ処理です。扱う値が2つになる以外は、ListやSetと変わりありません。

for((k,v) in mMap){
        println("${k}品目は$v")
    }

for文ではMapの各要素をk(キー)とv(バリュー)2つのローカル変数に分けて処理しています。

forEachでも基本的には同じです。ラムダ式の引数が2つになるので、->も記述しましょう。

mMap.forEach{(k, v)->println("${k}品目は$v")}

ただforEachでは引数をMap自体として、itで参照することもできます。

mMap.forEach{println("${it.key}品目は${it.value}")}

その場合はmap.key、map.valueとすることで、キーやバリューにアクセスできます。

おさらい

今回はMapの基本として、

  • Mapの特徴
  • 作成方法
  • Mapの中身の型
  • 値へのアクセス方法
  • MutableMapへの値の追加と削除
  • Mapのループ処理

以上のことについてお伝えしました。なおMapやMutableMapから呼び出せるメソッドは別記事でまとめているので、メソッドについて知りたい方はそちらをご覧ください。

[Kotlin]Map型プロパティとメソッド68種のまとめ
KotlinのMap型で定義されているプロパティ/メソッドは合わせて52。これに...
タイトルとURLをコピーしました