A partir de 2017, las respuestas anteriores parecen estar desactualizadas. Ejecuté algunos puntos de referencia (lista de 10 millones de Ints, primer partido aproximadamente en el medio, Scala 2.12.3, Java 1.8.0, Intel Core i5 de 1.8 GHz).A menos que se indique lo contrario, list
y map
tienen los siguientes tipos:
list: scala.collection.immutable.List
map: A => Option[B]
simplemente llame map
en la lista: ~ 1000 ms
list.map(map).find(_.isDefined).flatten
primera llamada toStream
en la lista: ~ 1200 ms
list.toStream.map(map).find(_.isDefined).flatten
Llame toStream.flatMap
en la lista: ~ 450 ms
list.toStream.flatMap(map(_).toList).headOption
llamada flatMap
en la lista: ~ 100 ms
list.flatMap(map(_).toList).headOption
primera llamada iterator
en la lista: ~ 35 ms
list.iterator.map(map).find(_.isDefined).flatten
función recursiva 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
}
}
}
Función iterativa 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
}
Puede acelerar aún más las cosas mediante el uso de Java en lugar de colecciones Scala y un estilo menos funcional.
bucle sobre los índices de 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
}
bucle sobre índices en java.util.ArrayList
con función que devuelve null
en lugar de 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
}
(Por supuesto, uno por lo general declare el tipo de parámetro como java.util.List
, no java.util.ArrayList
. Escogí este último aquí porque es la clase que utilicé para los puntos de referencia. Otras implementaciones de java.util.List
mostrará un rendimiento diferente; la mayoría será peor).
Si no me confundo, también se puede usar "flatMap" en Option, así que creo "y luego (_.toList) "es superfluo –
@Jens si lo prueba, verá que no funciona. –
val l = Lista (1, 2, 3, 4, 5, 6) diversión def (i: int) = { si (i == 3) Algunos (3) otro Ninguno } println (l .flatMap (fun (_)). head) println (l.flatMap (fun (_)). headOption) –