2010-07-13 17 views
44

Ho bisogno di un comparatore come parte di un modello di strategia che può utilizzare l'ordinamento naturale degli oggetti o un ordinamento personalizzato. Per il caso ordinamento naturale, ho scritto un semplice comparatore di prezzi:Esiste un comparatore naturale nell'API standard?

private static class NaturalComparator<T extends Comparable<? super T>> implements Comparator<T> { 
    @Override 
    public int compare(T o1, T o2) { 
     return o1.compareTo(o2); 
    } 
} 

sembra abbastanza semplice, ma mi chiedevo se qualcuno sapeva di uno nel API standard. Ho guardato TreeMap, e lo fa senza una tale classe, quindi quando quel codice è stato scritto, la risposta apparente sarebbe no, ma forse è stata aggiunta in seguito.

+4

Forse merita una menzione: al di fuori delle API standard, v'è di Guava Ordering.natural (). –

risposta

47

Aggiunto a Comparator in Java 8:

static <T extends Comparable<? super T>> Comparator<T> naturalOrder() 

usare in questo modo, per esempio:

Comparator<Double> natural = Comparator.<Double>naturalOrder(); 
return natural.compare(1.0, 1.1)); 
+12

Se non si utilizza ancora Java 8 e si desidera utilizzare il Comparatore in qualcosa di semplice come' Arrays.sort() ' o 'Collections.sort()', puoi semplicemente passare 'null' all'argomento Comparator, e userà l'ordine naturale. Tuttavia, non tutti gli usi di Comparator sono garantiti. Almeno per 'Arrays' e' Collections', funziona in questo modo. – Joe

+0

@Gioco se si usano matrici, la classe degli elementi dell'array deve implementare l'interfaccia 'Comparable' – natinusala

2

Non ho familiarità con un comparatore predefinito in Java, ma ovviamente, Comparator da confrontare è spesso un semplice wrapper.

Non esiste un generale di "ordinamento naturale" nell'API standard, sebbene alcuni tipi incorporati, come i numeri, abbiano un'implementazione di confronto, che diventa quindi il loro ordinamento naturale.

TreeMap e TreeSet e tutti questi devono generare un RuntimeException se l'oggetto inserito non implementa Comparable. Ad esempio, potresti inserire stringhe o numeri ma non un'altra raccolta.

Il codice di TreeMap non utilizza un comparatore se non è disponibile, utilizza invece lo compareTo. Per utilizzare compareTo, esegue il cast su Comparable, che è la fonte delle eccezioni.

private int compare(K k1, K k2) { 
     return (comparator==null ? ((Comparable <K>)k1).compareTo(k2) 
           : comparator.compare((K)k1, (K)k2)); 
    } 
+1

a proposito, in Java l'implementazione Comparable si chiama Natural Ordering: http://www.filigris.com/products/docflex_javadoc/examples/new/java/lang/Comparable.html#compareTo%28T%29 – Yishai

+0

@Yishai : Ah. Non ero conscio di ciò. Avrei pensato che Java evitasse il termine come incendio perché compareTo potrebbe avere un ordinamento arbitrario che potrebbe non corrispondere all'ordinamento naturale matematico oa qualsiasi ordinamento nel dominio di origine. (ad esempio, l'ordinamento delle stringhe non è "naturale" nel senso che non è un puro ordine di linguaggio naturale) – Uri

9

JDK non ce l'ha, ma è chiamato ComparableComparator ed esiste in molti contesti, come Spring, Apache Commons, Hibernate e molti altri

+16

FYI, Guava lo chiama 'Ordering.natural()'. –

1

Penso che se una classe ha un ordinamento naturale, è più comune in Java implementare Comparable piuttosto che avere un'implementazione Comparator per ogni classe.

Pertanto, se gli oggetti in questione hanno un ordine naturale definito, devono implementare Comparable e definire il metodo compareTo. Non c'è bisogno di andare a cercare uno Comparator. La maggior parte delle classi in java.util accetta uno Comparator facoltativo se viene imposto un ordinamento specifico o semplicemente tenta di chiamare compareTo sugli oggetti se non è specificato nessun altro ordine.

Quindi, per farla breve: implementare Comparable ogni volta che si desidera imporre un ordinamento naturale su una classe, utilizzare solo un Comparator quando si desidera qualcosa di diverso dall'ordinamento naturale.

+1

@downvoter: si prega di spiegare il motivo di un downvote. È possibile che io abbia commesso un errore o sbaglio, ma non aiuta se io (o l'OP) non so cosa sia. – MAK

+1

MAK, anche se non ho fatto un downvote, non ho votato neanche perché evade la domanda. A volte si desidera ordinare una classe in base al modello di strategia (nel mio caso si tratta di un sottotipo di un ordinamento alfanumerico più grande), quindi non si desidera un percorso di codice separato per l'ordinamento naturale (il codice TreeMap è piuttosto brutto a causa di non farlo, anche se potrebbero aver avuto motivi di prestazioni per fare quello che hanno fatto). – Yishai

+0

Sono assolutamente d'accordo su downvoting senza un commento, però. – Yishai

44

Sì, il JDK ce l'ha sicuramente! Eccolo:

Collections.reverseOrder(Collections.reverseOrder())

Sto scherzando. (Ma è vero. (Basta non usarlo.) (Mai.)))

+4

Non accetto questa risposta perché è stata superata da Java 8, ma è la risposta giusta per pre-Java 8. Ma in realtà non la uso ;-). – Yishai

+2

+1 per la maggior parte della risposta comica e ancora migliore :) –

+1

Mi può mancare lo scherzo qui. Perché non dovrei effettivamente usarlo (nel vecchio Java)? Qui non si sta davvero invertendo nulla. Il sovraccarico è molto modesto. –

Problemi correlati