2012-08-01 2 views
37

Diciamo che abbiamo un insieme di elementi:Come arrivare elemento max() dalla lista a Guava

class Item { 
    public String title; 
    public int price; 
} 

List<Item> list = getListOfItems(); 

Vorrei ottenere un elemento con un prezzo massimo di tale elenco con biblioteca Guava (con Ordering, presumo). Intendo qualcosa di simile a questo codice Groovy:

list.max{it.price} 

Come faccio? Quanto è efficiente?

risposta

55
Ordering<Item> o = new Ordering<Item>() { 
    @Override 
    public int compare(Item left, Item right) { 
     return Ints.compare(left.price, right.price); 
    } 
}; 
return o.max(list); 

è come efficiente come può essere: esso scorre l'elementi della lista, e restituisce il primo degli articoli che hanno il prezzo massimo: O (n).

+0

se il prezzo non è int. Sono in guava modo di utilizzare questo approccio? – gstackoverflow

+0

Il tipo di prezzo è irrilevante. Devi solo fornire un ordine che confronta gli articoli per prezzo. Diciamo che è BigDecimal, dovresti usare 'return left.price.compareTo (right.price)'. –

34

Secondo la risposta di JB, è anche possibile utilizzare alcuni stenografia quando si lavora con i valori che hanno ordine naturale, per esempio:

Ordering.<Integer> natural().max(listOfIntegers); 

Vedi Ordering.natural() per i dettagli.

11

È possibile farlo senza Guava.

Collezioni fornisce min e max metodi che operano su qualsiasi raccolta, compresi i sovraccarichi che richiedono comparatori. Qui usiamo i metodi statici di Java 8 comparatore con un lambda per specificare in modo conciso un comparatore, ma prima di Java 8 è possibile utilizzare una classe anonima:

Item max = Collections.max(list, Comparator.comparingInt(i -> i.price)); 

Questi metodi gettano NoSuchElementException se la raccolta è vuota.


Java 8 flussi forniscono min e max funzioni prendendo un comparatore. Queste funzioni restituiscono Optional<T> per gestire con garbo lo stream che è vuoto. I metodi statici in Comparator sono utili per specificare in modo conciso i comparatori, incluso il caso comune dell'ordine naturale. Per questa domanda, utilizza

Optional<Item> max = list.stream().max(Comparator.comparingInt(i -> i.price)); 

questo lavoro per qualsiasi sorgente d'acqua, che comprende tutte le implementazioni di raccolta, così come altre cose come i file, e rende facile per calcolare il massimo di un sottoinsieme di un raccolta filtrando il flusso. Se si dispone di una raccolta di grandi dimensioni e di un comparatore costoso (ad esempio, l'ordinamento naturale di String), è possibile utilizzare un flusso parallelo.

(A parte:. Idealmente flusso fornirebbe min e max sovraccarichi che assumono alcun argomento quando il tipo di flusso implementa Comparable Purtroppo Java non supporta condizionale esporre metodi basati su un parametro di tipo, e non vale la pena introdurre una nuova StreamOfComparable interfaccia che estende Stream solo per questo caso.)