The two underscores mean different things. First off, a bare underscore as part of a function argument will get turned into a lambda expression (see What are all the uses of an underscore in Scala). So your code
DataMapping.myMap.find(_._2.contains(Y)).map(_._1).get
is equivalent to
DataMapping.myMap.find(x => x._2.contains(Y)).map(x => x._1).get
Now, all of the sequencing functions, such as find
and map
, act on 2-tuples (K, V)
when applied to a Map[K, V]
. We're iterating over pairs, where the first element of the pair is the key and the second is the value. In Scala, we can access the Nth element (1-indexed) of a tuple with _N
, so if we have a pair val myPair = ("a", "b")
, then myPair._1
is "a"
and myPair._2
is "b"
.
The .find
call is checking whether the value (i.e. the second element of the pair) contains Y
. .find
returns an Option[(K, V)]
, since we were iterating over a sequence of (K, V)
. Now Option
is a container like any other, just with the restriction that it can contain at most one element. So Option.map
has the net effect of applying a function to the inside of the Option
(if it exists) and doing nothing if given None
. In our case, we've got an Option[(K, V)]
and we just care about the first part, so we want an Option[K]
. If there's something in the Option
, we do x => x._1
to get the first element of that tuple. If there's None
, then we just keep the value as None
.
Option.get
is an assertion that the Option
is non-empty. It throws an exception if that's wrong.
In summary, that code takes the map DataMapping.myMap
, finds the first element of your mapping whose value contains Y
, and then gets the corresponding key, throwing an exception if we can't find any such element.
Since we do a .get
right after, the .map
is sort of pointless in this case. I would probably have written this code as
DataMapping.myMap.find(_._2.contains(Y)).get._1
And, personally, I'm not super fond of the _N
syntax to begin with, so I might have gone one step further.
val (key, _) = DataMapping.myMap.find((_, v) => v.contains(Y)).get
or, in Scala 2 (before we had automatic case destructuring)
val (key, _) = DataMapping.myMap.find { case (_, v) => v.contains(Y) }.get