Java-8: Finden-index der minimale Wert aus einer Liste
Sagen, ich habe eine Liste mit Elementen (34, 11, 98, 56, 43)
.
Verwendung von Java-8-streams, wie finde ich den index des minimalen Elements in der Liste (z.B. 1 in diesem Fall)?
Ich weiß, dies kann leicht getan werden in Java mit list.indexOf(Collections.min(list))
. Aber ich freue mich auf eine Scala, wie die Lösung, wo wir können einfach sagen List(34, 11, 98, 56, 43).zipWithIndex.min._2
um den index der minimale Wert.
Gibt es etwas, das getan werden kann mithilfe von streams oder lambda-Ausdrücke (z.B. Java-8-spezifischen features), um das gleiche Ergebnis zu erzielen.
Hinweis: Dies ist nur für das lernen Zweck. Ich habe kein problem in der Verwendung Collections
utility-Methoden.
InformationsquelleAutor Mubin | 2015-06-29
Du musst angemeldet sein, um einen Kommentar abzugeben.
Als @TagirValeev erwähnt in seine Antwort, können Sie vermeiden, Boxen mithilfe
IntStream#reduce
stattStream#min
, aber auf Kosten der Verschleierung der Absicht:zipWithIndex
Fall, aber vielleicht ist die Redewendung Möglichkeit, dies zu lösen. Ich würde haltorElse(-1)
statt.InformationsquelleAutor Misha
Könnte man es so machen:
Wenn die Liste random-access-Liste
get
ist eine Konstante Zeit den Betrieb. Die API fehlt eine standard-tuple-Klasse, so habe ich dasSimpleEntry
von derAbstractMap
- Klasse als Ersatz.So
IntStream.range
erzeugt einen Strom von Indizes aus der Liste, aus der Sie die Zuordnung der einzelnen index auf den entsprechenden Wert. Dann bekommen Sie das minimale element, indem ein Komparator die Werte, auf die (von der Liste). Von dort haben Sie die Karte derOptional<SimpleEntry<Integer, Integer>>
zu einemOptional<Integer>
aus dem man den index (oder -1, wenn das optional ist leer).Als ein beiseite, ich würde wahrscheinlich verwenden eine einfache for-Schleife, um den index des Minimums, als die Kombination von
min
/indexOf
hat 2 Pässe über die Liste.Sie könnten auch interessiert sein zu überprüfen, Zipping-streams mit JDK8 mit lambda - (java.util.stream.Streams.zip)
Collections
oder 'Scala' s Umsetzung.InformationsquelleAutor Alexis C.
Da dies für das lernen erleichtern, lassen Sie uns versuchen, eine Lösung zu finden, die nicht nur irgendwie verwenden einen Strom, der aber tatsächlich funktioniert auf den stream von unsere Liste. Wir wollen auch nicht davon ausgehen, random access.
So, es gibt zwei Möglichkeiten, um ein nicht-triviales Ergebnis aus einem stream:
collect
undreduce
. Hier ist eine Lösung verwendet, die eine collector:Schreiben einen Sammler erstellt eine lästige Menge code, aber es kann leicht verallgemeinert zu unterstützen vergleichbaren Wert. Auch das aufrufen der Kollektor sieht sehr idiomatisch:
Wenn wir die änderung der
accept
undcombine
Methoden, um immer wieder eine neueMinimum
Instanz (dh. wenn wirMinimum
immutable), können wir auchreduce
:Spüre ich großes Potenzial für die Parallelisierung.
Collector.of(Minimum::new, Minimum::accept, Minimum::combine, Minimum::getIndex)
statt der Definition einer anonymen Klasse.Dieser Ansatz hat den Vorteil, ohne dass die Liste auf dem random-access-freundlich. Beachten Sie, dass
combine
Methode sollte korrekt behandelt den Fall vonother
leer.Collector
javadoc-erfordert ausdrücklich, dass für die parallel-Freundlichkeit als "Identitäts-Zwang". Es sagt nichts über den Umgang mit dem Fall vonthis
leer undother
nicht leer, aber es scheint ratsam zu behandeln, wie gut.ja, es hat einige kleinere Probleme, aber ich mag die Idee. Btw, es funktioniert ganz schnell, auf einige tests, es übertrifft sogar meine
IntStreamEx.minBy
. Ich commit eine Feste version, wahrscheinlich wird es in meine lib.InformationsquelleAutor Cephalopod
Hier sind zwei mögliche Lösungen, mit meinem StreamEx Bibliothek:
Oder:
Die zweite Lösung intern ist sehr nahe an einer vorgeschlagen von @AlexisC. Die erste ist wahrscheinlich die Schnellste, da es nicht mit Boxen (intern es ist eine Verringerung Betrieb).
Ohne Verwendung von Drittanbieter-code @Mischa ' s Antwort sieht für mich am besten.
InformationsquelleAutor Tagir Valeev