As of 2017, the previous answers seem to be outdated. I ran some benchmarks (list of 10 million Ints, first match roughly in the middle, Scala 2.12.3, Java 1.8.0, 1.8 GHz Intel Core i5). Unless otherwise noted, list
and map
have the following types:
list: scala.collection.immutable.List
map: A => Option[B]
Simply call map
on the list: ~1000 ms
list.map(map).find(_.isDefined).flatten
First call toStream
on the list: ~1200 ms
list.toStream.map(map).find(_.isDefined).flatten
Call toStream.flatMap
on the list: ~450 ms
list.toStream.flatMap(map(_).toList).headOption
Call flatMap
on the list: ~100 ms
list.flatMap(map(_).toList).headOption
First call iterator
on the list: ~35 ms
list.iterator.map(map).find(_.isDefined).flatten
Recursive function find()
: ~25 ms
def find[A,B](list: scala.collection.immutable.List[A], map: A => Option[B]) : Option[B] = {
list match {
case Nil => None
case head::tail => map(head) match {
case None => find(tail, map)
case result @ Some(_) => result
}
}
}
Iterative function find()
: ~25 ms
def find[A,B](list: scala.collection.immutable.List[A], map: A => Option[B]) : Option[B] = {
for (elem <- list) {
val result = map(elem)
if (result.isDefined) return result
}
return None
}
You can further speed up things by using Java instead of Scala collections and a less functional style.
Loop over indices in java.util.ArrayList
: ~15 ms
def find[A,B](list: java.util.ArrayList[A], map: A => Option[B]) : Option[B] = {
var i = 0
while (i < list.size()) {
val result = map(list.get(i))
if (result.isDefined) return result
i += 1
}
return None
}
Loop over indices in java.util.ArrayList
with function returning null
instead of None
: ~10 ms
def find[A,B](list: java.util.ArrayList[A], map: A => B) : Option[B] = {
var i = 0
while (i < list.size()) {
val result = map(list.get(i))
if (result != null) return Some(result)
i += 1
}
return None
}
(Of course, one would usually declare the parameter type as java.util.List
, not java.util.ArrayList
. I chose the latter here because it's the class I used for the benchmarks. Other implementations of java.util.List
will show different performance - most will be worse.)