[AD] Scalaアプリケーションの開発・保守は合同会社ミルクソフトにお任せください
この記事では get
、getOrElse
、apply
、applyOrElse
メソッドの使い方、使い分けについて解説します。
使い分け早わかり!
get
、getOrElse
、apply
、applyOrElse
の使い分けについては、
以下の問いに答えていけば自ずと導かれます。
早速、それぞれのメソッドの使い方について見ていきましょう。
get メソッドの使い方
以下のマップについて見てみます。
case class Person(firstName: String, lastName: String, age: Int) val people: Map[Int, Person] = Map( 1 -> Person("Andrea", "Thompson", 23), 2 -> Person("Austin", "May", 17), 3 -> Person("John", "Winston", 18), 4 -> Person("Christina", "Chandler", 20), 5 -> Person("John", "Thompson", 23) )
get
はいちばん基本のメソッドです。
戻り値がOption
なので、値がある場合とない場合のそれぞれに対応することができます。
値がある場合には、以下のように Some
に包まれた値を得ることができます。
println( people.get(1) )
Some(Person(Andrea,Thompson,23))
値がない場合についても見てみましょう。
値がない場合には None
が返ってくるので、安全に処理することができます。
println( people.get(100) )
None
getOrElse メソッドの使い方
値がない場合の値が既に決まっている場合には、 getOrElse
を使用することができます。
キーに対応する値があれば、その値がそのまま返ってきます。
println( people.getOrElse(1, "NO NAME") )
Person(Andrea,Thompson,23)
値がない場合には、デフォルト値が返ってきます。
println( people.getOrElse(100, "NO NAME") )
NO NAME
計算量節約のためのメモ
getOrElse
の第2引数に渡すデフォルト値は、名前渡しになっています。
名前渡しになっているということは、このデフォルト値は「なかった場合」のみ、その都度評価されるということです。
したがって計算済みの値を渡すべきなのか、未評価のまま関数として渡すべきなのか、検討の余地があります。
applyOrElse メソッドの使い方
使い方は getOrElse
と同じです。
getOrElse
との使い分け方としては、無かった場合の処理として
「第一引数に渡した値を取るfunction1〜functionN」を渡す場合には、applyOrElse
を使います。
具体的に見てみましょう。
次の関数を定義します。
キーを渡すとキーを含んだエラーメッセージをを返してくれる関数です。
def errorMessage(id: Int): String = s"NO NAME; id=$id"
applyOrElse
に第2引数に先程定義した関数を渡してみましょう。
引数リストを省略することでFunction1として渡すことができます。
値がある場合には期待通りの値を出力します。
println( people.applyOrElse(1, errorMessage) )
Person(Andrea,Thompson,23)
ない場合についても見てみましょう。
期待通り、エラーメッセージが出力されています。
println( people.applyOrElse(100, errorMessage) )
NO NAME; id=100
備考
applyOrElse
は partialFunction
のメソッドです。
したがってMapに限らず、partialFunction
を継承しているクラス、例えば List
や Set
でも使うことができます。
apply メソッドの使い方
「いやいや apply
には値の存在するキーしか渡さないので大丈夫です」と断言できる場合には apply
メソッドを使うことができます。
apply
は省略できるので、以下のようにスッキリ書くことができます。
戻り値も期待通り。
println( people(1) )
Person(Andrea,Thompson,23)
ただし、そう言いつつも実際にはキーがありませんでした、となると盛大に例外が飛びます。
残念でしたでは済みませんので、細心の注意を払ってください。
println( people(100) )
たとえば、もし仕様変更で予期せぬ値が渡ってきた場合には…?
ほら、言わんこっちゃないですね。
java.util.NoSuchElementException at scala.collection.immutable.BitmapIndexedMapNode.apply(HashMap.scala:608) at scala.collection.immutable.HashMap.apply(HashMap.scala:131) ... 36 elided
「仕様変更により値のないキーが渡ってくるようになる」ような可能性が後々まで絶対無いですとも言い切れない場合には、
apply
はできるだけ使わないようにして、get
などを使うことをおすすめします。
まとめ
まずは get
を使いましょう。
デフォルト値を扱いたい場合はその内容に応じて getOrElse
と applyOrElse
を使い分けましょう。
そして、apply
のことはなるべく忘れましょう。
あらためて順を追って述べると、以下のようになります。
- キーに対応する値が絶対に存在するとは言い切れない場合は、
get
、getOrElse
、applyOrElse
のいずれかを使います。 - 値が無いからといってデフォルトで返したい値が特に無い場合は
get
を使います。 - 値が無いときのデフォルト値/処理がある場合は、
getOrElse
またはapplyOrElse
を使います。 - デフォルト値/処理が「このメソッドに渡した値(つまりキー)をとる関数の実行結果」である場合は
applyOrElse
を使います。 - そうではない場合、つまりデフォルト値が定数であったり、キーとは関連がない処理の場合には
getOrElse
を使用します。 - そして、「キーに対応する値は絶対に存在する。間違いない」と自信を持って断言できる場合には
apply
を使っても良いでしょう。
以上です。
手に使い分けていきましょう。