Kotlin ist Iterierbar und Reihenfolge genau der gleiche. Warum sind zwei Typen, die erforderlich sind?
Beide interfaces definieren nur eine einzige Methode
public operator fun iterator(): Iterator<T>
Dokumentation sagt Sequence
gemeint ist, faul zu sein. Aber nicht Iterable
faul zu (es sei denn, unterstützt durch eine Collection
)?
InformationsquelleAutor Venkata Raju | 2016-02-25
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der wesentliche Unterschied liegt in der Semantik und der Implementierung des stdlib-Erweiterungsfunktionen für
Iterable<T>
undSequence<T>
.Für
Sequence<T>
, die Erweiterung der Funktionen führen träge, wo möglich, ähnlich zu Java-Streams intermediate Operationen. Zum Beispiel,Sequenz<T>.map { ... }
gibt andereSequence<R>
und nicht wirklich bei der Verarbeitung der Produkte, bis ein terminal Betrieb wietoList
oderfold
genannt wird.Betrachten Sie diesen code:
Er druckt:
Sequence<T>
ist bestimmt für faul, Nutzung und effizientes pipelining-wenn Sie möchten, reduzieren Sie die Arbeit, die in terminal Operationen so viel als möglich, das gleiche zu Java-Streams. Aber Faulheit bringt einigen overhead, was unerwünscht ist für die gemeinsame einfache Transformationen von kleineren Sammlungen und macht Sie weniger performant.In der Regel ist es kein guter Weg, um zu bestimmen, wenn es gebraucht wird, also in Kotlin stdlib Faulheit wird explizit gemacht und extrahiert, um die
Sequence<T>
Schnittstelle zu verwenden, vermeiden Sie es auf alleIterable
s standardmäßig.Für
Iterable<T>
im Gegenteil, die Erweiterung der Funktionen mit intermediate Betrieb Semantik arbeiten eifrig, die Ware sofort und bringe eine andereIterable
. Zum Beispiel,Iterierbar<T>.map { ... }
gibt eineList<R>
mit der mapping-Ergebnisse.Der entsprechende code für Iterierbar:
Dieser druckt:
Wie gesagt,
Iterable<T>
ist nicht faul, standardmäßig, und diese Lösung zeigt sich auch: in den meisten Fällen hat es gut locality of reference damit die Vorteile des CPU-cache -, Vorhersage -, prefetching etc. so dass auch mehrere kopieren einer collection funktioniert immer noch gut genug und eine bessere Leistung in einfachen Fällen mit kleinen Sammlungen.Wenn Sie mehr Kontrolle über die Auswertung der pipeline, es gibt eine explizite Konvertierung in eine lazy sequence mit
Iterierbar<T>.asSequence()
Funktion.Java
(meistGuava
) fansfür die funktionale Menschen, die Sie werden überrascht sein, die alternative faul standardmäßig.
Lazy per default ist in der Regel weniger performant für kleinere und Häufig verwendete Kollektionen. Eine Kopie kann schneller sein als ein lazy eval, wenn unter Ausnutzung der CPU-Caches und so weiter. Also für übliche Anwendungsfälle besser ist, nicht faul zu sein. Und leider sind die gemeinsamen Verträge für Funktionen wie
map
,filter
und andere haben einfach nicht genügend Informationen, um zu entscheiden, andere als die von der Quelle Sammlung geben, und da die meisten Sammlungen sind auch Durchsuchbar, das ist kein guter marker für "faul", weil es allgemein ÜBERALL. faul muss explizit erfolgen, um sicher zu sein.Ein Beispiel aus einer aktuellen Apache Spark Ankündigung, sind Sie sich Gedanken über das offensichtlich finden Sie unter "Cache-aware-Berechnung" - Abschnitt an databricks.com/blog/2015/04/28/... ... aber Sie sind besorgt über die Milliarden von Dingen Durchlaufen, so dass Sie gehen müssen, um die volle extreme.
Zusätzlich, ein häufiges Problem mit lazy evaluation ist die Erfassung der Kontext und die Lagerung entstehenden faul Berechnung in einem Feld zusammen mit den aufgenommenen einheimischen und was Sie halten. Daher schwer zu Debuggen, Speicher-Lecks.
InformationsquelleAutor hotkey
Abschluss hotkey ' s Antwort:
Ist es wichtig, zu bemerken, wie Sequenz-und Durchsuchbar durchläuft während Ihrer Elemente:
Sequenz Beispiel:
Log Ergebnis:
filter - Map -, filter - Map - Jeder
Iterierbar Beispiel:
filter - filter - Map - Karte - Jede - Jedes
Dies ist ein gutes Beispiel.
InformationsquelleAutor Leandro Borges Ferreira