2015-09-30 10 views
5

List classe in Java 8 è stato aggiunto un nuovo metodo sort. Qualcuno potrebbe per favore chiarire quando dovrei preferire usare questo al contrario del metodo Collections.sort(..)?Java 8 List.sort usage

risposta

3

Si dovrebbe andare per List.sort.

Esempio di utilizzo List.sort, per ordinare un elenco di stringa per quanto riguarda la lunghezza degli elementi:

List<String> list = new ArrayList<>(Arrays.asList("aa", "aaa", "a")); 
list.sort(comparing(String::length)); 

Collections.sort() è stato il modo di pre-Java 8 di fare questo. Si noti che non vi è alcuna reale differenza tra i due. Se si dà un'occhiata al Collections.sort codice sorgente, si può notare che chiama list.sort:

public static <T extends Comparable<? super T>> void sort(List<T> list, Comparator<? super T> c) { 
    list.sort(c); 
} 
+0

Sì, sembra 'Collections.sort' è delegata a' List.sort' in JDK1 .8. – Unihedron

+4

Non c'è niente che 'List.sort' faccia meglio riguardo a" sfruttare le espressioni lambda "di' Collections.sort'. Il vantaggio di 'List.sort' è che le implementazioni di' List' possono sovrascriverlo e fornire implementazioni più efficienti, ad es. 'ArrayList' elimina il passaggio di copia dell'implementazione predefinita ordinando direttamente il suo array interno. Poiché 'Collections.sort' delega a' List.sort', non importa quale metodo usi, in entrambi i casi otterrai tale vantaggio. – Holger

0

lo deve usare quando fornire il proprio confronto. Per esempio:

list.sort(Comparator.reverseOrder()); 

Invece di: classe

Collections.sort(list); 
Collections.reverse(list); 
+4

Si potrebbe anche scrivere: 'Collections.sort (list, Comparator.reverseOrder())' ... – assylias

0

Lista come parte di JSR 335 modifiche e siamo in grado di fare uso di tale metodo per ordinare l'elenco:

// Utilizzando un ordine nella lista.

personList.sort ((p1, p2) -> p1.firstName.compareTo (p2.firstName));

--prima di java 8 possiamo utilizzare solo questa segale --- Collections.sort (elenco persone, (p1, p2) -> p1.firstName.compareTo (p2.firstName));

4

Non c'è alcuna differenza funzionale perché Collections.sort(list) chiama list.sort(null) e Collections.sort(list, comparator) chiamate list.sort(comparator).

Quindi è solo una questione di stile: quando si fornisce il proprio comparatore, chiamare l'ordinamento nell'elenco è probabilmente più naturale e leggibile rispetto all'utilizzo di un metodo statico esterno.

Tuttavia, se si desidera ordinare l'elenco in ordine naturale, Collections.sort(list) è forse più chiaro di list.sort(null).

+1

Qualcuno sa perché non c'è 'list.sort()'? – user4235730

+3

@ user4235730, 'list.sort()' non è sicuro: potresti sicuro elenco non comparabile e il compilatore non ti fermerà. In realtà 'list.sort (null)' non è sicuro, quindi è preferibile usare 'Collections.sort (list)' o 'list.sort (Comparator.naturalOrder())', quindi se ti capita di passare la lista di non - elementi comparabili si avrà un errore di compilazione. –

3

Sebbene sia possibile utilizzare il metodo List.sort(Comparator), lo scopo principale di questo metodo è prioritario. Prima di Java-8 l'ordinamento di ogni era in qualche modo inefficace. Prima l'elenco è stato scaricato nell'array tramite il metodo toArray(), quindi l'array è stato ordinato e infine l'elenco è stato aggiornato tramite ListIterator.set. In Java-8 questo è il comportamento predefinito implementato nel metodo predefinito List.sort(Comparator). Tuttavia è possibile cambiarlo in sottoclassi se è possibile fornire un algoritmo più efficiente. Esempi:

  • ArrayList e Arrays.asList() forniscono proprio sort implementazione che ordina direttamente la matrice interna, quindi non è necessario copiare avanti e indietro.

  • CopyOnWriteArrayList può essere ordinato ora!Provate il seguente codice:

    List<String> list = new CopyOnWriteArrayList<>(Arrays.asList("a", "c", "b")); 
    Collections.sort(list); 
    

    In Java-7 si getta UnsupportedOperationException, perché sostenere ListIterator.set contraddice l'idea di questa lista (ogni iteratore itera l'istantanea indipendente). In Java-8 il ListIterator.set non è ancora supportato, ma questo codice funziona correttamente a causa dell'implementazione di ordinamento personalizzata.

  • Collections.singletonList e Collections.emptyList semplicemente non fare nulla (ordinamento 0 o 1 elemento è un no-op) che è sicuramente più veloce di creare un unico elemento o zero elemento di un array, ordinare e iterare lista per impostare il valore indietro .

  • Collections.unmodifiableList ora getta solo UnsupportedOperationException. Prima di Java-8 hai ottenuto l'eccezione solo dopo aver scaricato la lista immutabile nell'array, ordinando l'array e iniziando a scriverlo.


Ecco un esempio che può essere utile in codice utente. Supponiamo che si desidera creare una vista mappata di qualche lista: l'utilizzo

public class MappedList<T, R> extends AbstractList<R> { 
    private final List<T> source; 
    private final Function<? super T, ? extends R> mapper; 

    public MappedList(List<T> source, Function<? super T, ? extends R> mapper) { 
     this.source = source; 
     this.mapper = mapper; 
    } 

    @Override 
    public R get(int index) { 
     return mapper.apply(source.get(index)); 
    } 

    @Override 
    public int size() { 
     return source.size(); 
    } 
} 

Esempio:

List<String> list = Arrays.asList("a", "foo", "bb", "bar", "qq"); 
List<Integer> mappedList = new MappedList<>(list, String::length); 
System.out.println(mappedList); // prints [1, 3, 2, 3, 2] 

funziona bene, ma cercando Collections.sort(mappedList); otterrete UnsupportedOperationException (set operazione non funziona come non si può invertire la funzione di mappatura). Tuttavia, se si implementa il metodo sort() in MappedList, si sarà in grado di risolvere correttamente (cambiando l'elenco originale):

@Override 
public void sort(Comparator<? super R> c) { 
    @SuppressWarnings("unchecked") 
    Comparator<? super T> comparator = c == null ? 
     Comparator.comparing((Function<? super T, ? extends Comparable<Object>>) mapper) : 
     Comparator.comparing(mapper, c); 
    source.sort(comparator); 
} 

List<String> list = Arrays.asList("a", "foo", "bb", "bar", "qq"); 
List<Integer> mappedList = new MappedList<>(list, String::length); 
Collections.sort(mappedList); 
System.out.println(mappedList); // prints [1, 2, 2, 3, 3] 
System.out.println(list); // prints [a, bb, qq, foo, bar]