Java-Strom: finden Sie ein element mit min - /max-Wert eines Attributs
Habe ich einen Strom von Objekten und ich möchte denjenigen finden, der zu einem maximalen Wert eines Attributs, das ist aufwendig zu berechnen.
Als ein bestimmtes einfaches Beispiel, sagen, wir haben eine Liste von strings an und wir wollen das coolste, da eine coolnessIndex
Funktion.
Sollten die folgenden arbeiten:
String coolestString = stringList
.stream()
.max((s1, s2) -> Integer.compare(coolnessIndex(s1), coolnessIndex(s2)))
.orElse(null);
Nun, es gibt zwei Probleme mit diesem. Den ersten, vorausgesetzt, die coolnessIndex
ist aufwendig zu berechnen, dies wird wahrscheinlich nicht sehr effizient. Ich nehme an, die max
- Methode verwenden müssen, die Komparator-immer wieder, die wiederum rufen die coolnessIndex
wiederholt und am Ende wird es mehr als einmal aufgerufen werden für jede saite.
Zweiten, dass der Komparator führt zu Redundanz in den code. Ich würde viel lieber eine syntax wie diese:
String coolestString = stringList
.stream()
.maxByAttribute(s -> coolnessIndex(s))
.orElse(null);
Aber ich habe nicht in der Lage zu finden, eine entsprechende Methode in der Stream
API. Das überrascht mich, da die Suche nach min/max-durch ein Attribut scheint, wie ein gemeinsames Muster. Ich Frage mich, ob es einen besseren Weg, als mit dem Komparator (andere als eine for-Schleife).
InformationsquelleAutor der Frage Jan Pomikálek | 2016-04-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier ist eine Variante mit einem
Object[]
als ein Tupel, nicht der schönste code, aber prägnantInformationsquelleAutor der Antwort gustf
InformationsquelleAutor der Antwort frhack
Danke an alle für die Anregungen. Endlich fand ich die Lösung, die ich wie die meisten am Effizienz der Weg Komparator funktioniert - die Antwort von bayou.io:
Haben einen Allgemeinen Zweck
cache
Methode:Dies könnte dann wie folgt verwendet werden:
InformationsquelleAutor der Antwort Jan Pomikálek
Wie über die Verwendung von zwei streams, einen, eine map zu erstellen mit den vorab berechneten Werten und eine zweite mit den map-Eintrag zu finden, der max-Wert:
InformationsquelleAutor der Antwort kensei62
Ich würde eine lokale Klasse (eine Klasse definiert, die innerhalb einer Methode—selten, aber völlig legal), und ordnen Sie Ihre Objekte, also die teuerste Attribut ist genau berechnet, einmal für jedes:
InformationsquelleAutor der Antwort VGR
Können Sie nutzen die Idee der sammeln die Ergebnisse aus dem stream entsprechend. Die Einschränkung von teuren kühle Berechnung-Funktion macht Sie betrachten die Funktion aufrufen genau einmal für jedes element des Stroms.
Java 8 bietet die
collect
Methode auf dieStream
und eine Vielzahl von Möglichkeiten, in denen Sie verwenden können, Sammler. Es scheint, dass, wenn Sie verwendet dieTreeMap
zu sammeln, Ihre Ergebnisse, die Sie behalten können die Ausdruckskraft und gleichzeitig bleiben rücksichtsvoll Effizienz:Dieser code druckt die
stooge
mit maximaler coolness und diecoolness
- Methode aufgerufen wird genau einmal für jedenstooge
. DieBinaryOperator
die funktioniert wie diemergeFunction
((a, b) ->a
) weiter verbessert werden kann.InformationsquelleAutor der Antwort Kedar Mhaswade
Ist dies ein Rückgang problem. Reduzierung einer Liste bis zu einem bestimmten Wert. Im Allgemeinen reduzieren Sie arbeitet unten in der Liste Betriebssystem auf eine partielle Lösung und ein Element in der Liste. In diesem Fall würde das bedeuten, vergleicht man die früheren 'gewonnen' - Wert auf den neuen Wert aus der Liste, die berechnen die teure operation zweimal auf jeder Vergleich.
Laut https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html eine alternative ist die Nutzung sammeln, statt zu reduzieren.
Einer benutzerdefinierten Verbraucher - Klasse erlaubt die Verfolgung der teure Operationen, da es reduziert die Liste. Verbraucher können rund um die mehrere Aufrufe der teuren Berechnung durch die Zusammenarbeit mit änderbarer Zustand.
Diese Klasse nimmt einen string, und wenn es Kühler ist als die vorherigen Sieger, ersetzt es und spart die teuren berechneten Wert.
InformationsquelleAutor der Antwort GregA100k
erstellen Sie einfach Ihre (Ziel -, Metrik -) Paare erste:
(das sind com.googlecode.totallylazy.Pair)
InformationsquelleAutor der Antwort Paul Janssens