Scalaのマップとタプル

Scalaでハッシュマップみたいなのを作るときにはMapというクラスを使うと良いみたい。

var map = Map("key1"->"val1", "key2"->"val2")

で、Mapのコンストラクタに渡す値は「タプル」と呼ばれているのだそうだ。
この「タプル」というのが柔軟すぎてわけがわからなくなったので、忘れないようにメモしておく。

これ全部タプル

var t1 = 1 -> 2
var t2 = ( 1, 2 )
var t3 = Tuple(1,2)
var t4 = Tuple2(1,2)

「Tuple2」というのは、値を2つ持つタプルのことなのだと思う。値が3つになるとTuple3。

中途半端に型指定してコンパイルエラー

Scalaは型指定しなくても、初期化された値によって変数の型が決まる。

var t1 = 1 -> 2

って書いたら、t1の型は自動的に「Tuple[Int,Int]」に決まる。
[Int,Int]っていうのは型パラメータみたいなものです。

var t1:Tuple[Int,Int] = 1 -> 2

上のように明示的に型を指定してもよい。

var t1:Tuple = 1 -> 2

上のように中途半端に型を指定するとコンパイルエラーになりました。型を喰らわば皿までというか、英語のコンパイルエラーが読めない私はハマッてしまって往生しました。

本題のMap

Mapというはキーと値のペアを複数格納することができるコレクションなのですが、「キーと値のペア」というのが「タプル」で表されてるみたいです。

var m1 = Map( 1 -> 2 ) // 1 -> 2 はタプル
var m2 = Map( (1, 2) ) // ( 1, 2 ) もタプル。括弧のつかない「1,2」はタプルではない。
var m3 = Map( Tuple(1, 2) ) // Tuple(1 ,2)もタプル
var m4 = Map( Tuple2(1, 2) ) // Tuple2(1 ,2)もタプル

Mapに値を追加

Mapに値を追加しようと思ってもputメソッドはありませんでした。「+」演算子を使うようです。

var m1 = Map( 1 -> 2 )
m1 = m1 + ( 2 -> 3 )

「+=」も使えます。

var m1 = Map( 1 -> 2 )
m1 += ( 2 -> 3 )

異なる型の値を追加しようとすると容赦なくコンパイルエラーが飛んで来ます。

m1 + = ( "a" -> "b" ) // エラー!!

Mapから値を取得

Mapから値を取得するにはapplyを取得します。存在しないキーを指定すると例外が発生します。

var m1 = Map( 1 -> 2 )
m1.apply(1) // 2
m1.apply(2) // java.util.NoSuchElementExceptionが発生する

getというメソッドもあります。これを使うと「Some」クラスのオブジェクトが帰ってきます。存在しないキーを指定するとNoneオブジェクトが帰ります。

var m1 = Map( 1 -> 2 )
m1.get(1) // Some(2)
m1.get(2) // None

Tupleから値を取得

Tupleから値を取得するには「_」(アンダーバー)メソッドを使います。

var t1 = 10 -> 20 // Tuple2[Int,Int]
t1._1 // 10(1つめの値)
t1._2 // 20(2つめの値)
t1._3 // コンパイルエラー!

Tupleに値を追加

できるのかな? 多分できないと思う。

思ったこと

JavaのMapとまるで違う。
Java

Map<Integer, Integer> m = new HashMap<Integer, Integer>();

と書いていたのを思い出すと「記述量が減ったなあ」と思う。