Ho un flusso di oggetti e vorrei trovare quello con il valore massimo di qualche attributo che è costoso da calcolare.Java Stream: trova un elemento con un valore min/max di un attributo
Come esempio semplice specifico, diciamo che abbiamo una lista di stringhe e vogliamo trovare quella più bella, data una funzione coolnessIndex
.
Il seguente dovrebbe funzionare:
String coolestString = stringList
.stream()
.max((s1, s2) -> Integer.compare(coolnessIndex(s1), coolnessIndex(s2)))
.orElse(null);
Ora, ci sono due problemi con questo. Innanzitutto, supponendo che lo coolnessIndex
sia costoso da calcolare, probabilmente non sarà molto efficiente. Suppongo che il metodo max
dovrà utilizzare ripetutamente il comparatore, che a sua volta chiamerà ripetutamente lo coolnessIndex
e alla fine verrà chiamato più di una volta per ogni stringa.
In secondo luogo, dovendo fornire ai cavi del comparatore una certa ridondanza nel codice. Io preferirei di gran lunga la sintassi simile a questo:
String coolestString = stringList
.stream()
.maxByAttribute(s -> coolnessIndex(s))
.orElse(null);
Tuttavia, non sono stato in grado di trovare un metodo di corrispondenza nel Stream
API. Questo mi sorprende, dal momento che trovare min/max da un attributo sembra uno schema comune. Mi chiedo se c'è un modo migliore di usare il comparatore (diverso da un ciclo for).
correlati ma non del tutto duplicare: http://stackoverflow.com/questions/27606185/arg-max-in-java-8-streams (dove la la preoccupazione è la brevità del codice piuttosto che l'efficienza, e penso che la soluzione raccomandata finisca per chiamare ripetutamente l'equivalente di 'coolnessIndex'). –
Non credo che ci sia qualcosa di equivalente a questo nell'API di Java Streaming. Potresti implementare la tua versione di 'maxByAttribute' (qualcun altro ha fatto qualcosa del genere [qui] (https://gist.github.com/mapio/57299694ef94cc88dddb) ma non ho guardato il loro codice), o tu potrebbe usare 'map' per ottenere un flusso di coppie (' s', 'coolnessIndex (s)') e poi 'max' quelli - ma AIUI Java non ha una classe di coppia a portata di mano per cui si finisce con molto codice boilerplate, per non parlare di tutte le allocazioni extra di memoria. –
È possibile raggruppare per stringa-> risultati di coolness in una mappa e quindi scegliere la stringa più bella. Vedi https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toMap-java.util.function.Function-java.util.function.Function- –