2010-07-13 13 views
44

Necesito un comparador como parte de un patrón de estrategia que puede usar el orden natural de los objetos o algunos pedidos personalizados. Para el caso ordenamiento natural, escribí un comparador simple:¿Existe un comparador natural en la API estándar?

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

parece bastante simple, pero me preguntaba si alguien sabía de la una de la API estándar. Miré TreeMap, y lo hace sin esa clase, por lo que cuando se escribió ese código, la respuesta aparente sería no, pero tal vez se agregó más tarde.

+4

Tal vez vale la pena mencionar: Fuera de la API estándar, hay de guayaba Ordering.natural () –

Respuesta

47

Agregado a Comparator in Java 8:

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

utilizar de esta manera, por ejemplo:

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

Si aún no está utilizando Java 8, y desea usar el Comparador en algo simple como' Arrays.sort() ' o 'Collections.sort()', simplemente puede pasar 'null' al argumento de Comparador, y usará el orden natural. Sin embargo, no se garantiza que todos los usos de Comparator funcionen de esa manera. Al menos para 'Arrays' y' Collections', funciona de esa manera. – Joe

+0

@Joe si usa arrays, la clase de los elementos de la matriz debe implementar la interfaz 'Comparable' – natinusala

2

No estoy familiarizado con un comparador predeterminado en Java, pero obviamente, Comparator to compareTo es a menudo una mera envoltura.

No hay un general de "ordenamiento natural" en la API estándar, aunque ciertos tipos incorporados, como los números, tienen una implementación de compareTo que luego se convierte en su ordenamiento natural.

TreeMap y TreeSet y todos estos deberían arrojar una RuntimeException si el objeto que pones no implementa Comparable. Por lo tanto, por ejemplo, puedes lanzar cadenas o números pero no otra colección.

El código de TreeMap no utiliza un comparador si no está disponible, sino que usa compareTo. Para usar compareTo, realiza un lanzamiento a Comparable, que es el origen de las excepciones.

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

por cierto, en Java la implementación Comparable se llama Natural Ordering: http://www.filigris.com/products/docflex_javadoc/examples/new/java/lang/Comparable.html#compareTo%28T%29 – Yishai

+0

@Yishai : Ah. No estaba enterado de eso. Hubiera supuesto que Java evita el término como fuego porque comparar podría tener un orden arbitrario que puede no coincidir con el orden matemático natural o cualquier orden en el dominio de origen. (Por ejemplo, el orden de las cadenas no es "natural" en el sentido de que no es un orden de lenguaje natural puro) – Uri

9

JDK no lo tiene, sin embargo, se llama ComparableComparator y existe en muchos marcos como Spring, Apache Commons, Hibernate y muchos otros

+16

Para su información, Guava lo llama 'Ordering.natural()'. –

1

Creo que si una clase tiene un orden natural, es más habitual en Java que implemente Comparable en lugar de tener una implementación de Comparator para cada clase.

Por lo tanto, si los objetos en cuestión tienen un orden natural definido, deben implementar Comparable y tienen el método compareTo definido. No hay necesidad de buscar un Comparator. La mayoría de las clases en java.util toman un Comparator opcional si se va a imponer un pedido específico, o simplemente intentan llamar al compareTo en los objetos si no se especifica ningún otro pedido.

Por lo tanto, abreviatura larga: Implemente Comparable siempre que quiera imponer un orden natural en una clase, solo use un Comparator cuando desee algo distinto al orden natural.

+1

@downvoter: explique el motivo de un voto negativo. Es muy posible que haya cometido un error o esté completamente equivocado, pero no ayuda si yo (o el OP) no sé de qué se trata. – MAK

+1

MAK, aunque no perdoné, no voté tampoco porque evade la pregunta. A veces quieres que una clase ordene según el patrón de estrategia (en mi caso es un subtipo de una clase alfanumérica más grande), por lo que no quieres una ruta de código separada para ordenamiento natural (el código de TreeMap es bastante feo debido a no hacer esto, aunque pueden haber tenido razones de rendimiento para hacer lo que hicieron). – Yishai

+0

Definitivamente estoy de acuerdo con la votación negativa sin hacer ningún comentario. – Yishai

44

Sí, el JDK definitivamente lo tiene! Aquí está:

Collections.reverseOrder(Collections.reverseOrder())

Es broma. (Pero es verdad. (Simplemente no use eso.) (Nunca.)))

+4

No acepto esta respuesta porque ha sido superada por Java 8, pero es la respuesta correcta para pre-Java 8. Pero no la utilizo ;-). – Yishai

+2

+1 para la respuesta más cómica y sin embargo mejor :) –

+1

Me puede estar perdiendo la broma aquí. ¿Por qué no debería usarlo (en Java anterior)? Nada está siendo revertido aquí. La sobrecarga es muy modesta. –

Cuestiones relacionadas