Od 2017 r. Poprzednie odpowiedzi wydają się nieaktualne. Przeprowadziłem testy porównawcze (lista 10 milionów int, pierwszy mecz mniej więcej pośrodku, Scala 2.12.3, Java 1.8.0, 1.8 GHz Intel Core i5).O ile nie zaznaczono inaczej, list
i map
mają następujące typy:
list: scala.collection.immutable.List
map: A => Option[B]
Wystarczy zadzwonić map
na liście: ~ 1000 ms
list.map(map).find(_.isDefined).flatten
najpierw wywołać toStream
na liście: ~ 1200 ms
list.toStream.map(map).find(_.isDefined).flatten
Zadzwoń na toStream.flatMap
z listy: ~ 450 ms
list.toStream.flatMap(map(_).toList).headOption
połączeń flatMap
na liście: ~ 100ms
list.flatMap(map(_).toList).headOption
najpierw wywołać iterator
na liście: ~ 35 ms
list.iterator.map(map).find(_.isDefined).flatten
funkcji rekurencyjnej 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
}
}
}
Funkcja iteracyjna 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
}
można dodatkowo przyspieszyć rzeczy za pomocą Java zamiast kolekcji Scala i styl mniej funkcjonalne.
pętli nad wskaźników w 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
}
pętli nad wskaźników w java.util.ArrayList
z funkcją powrotu null
zamiast 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
}
(Oczywiście, zazwyczaj zadeklaruj typ parametru jako java.util.List
, a nie java.util.ArrayList
. Wybrałem ten ostatni tutaj, ponieważ jest to klasa, której użyłem do testów porównawczych.wyświetli inną wydajność - większość będzie gorsza.)
Jeśli nie jestem zdezorientowany przeze mnie, "flatMap" może być również użyty w opcji, więc myślę "i wtedy (_.toList) "jest zbędny –
@ Jen, jeśli go wypróbujesz, zobaczysz, że to nie działa. –
Val L = Lista (1, 2, 3, 4, 5, 6) def zabawy (I int) = { gdy: (i == 3) Część (3) inny Brak } println (l .flatMap (fun (_)). head) println (l.flatMap (fun (_)). headOption) –