2010-05-18 10 views
34

Comparable contrato especifica que debe lanzar e.compareTo(null)NullPointerException.contrato Comparable y Comparator en lo que respecta a null

De the API:

Tenga en cuenta que null no es una instancia de cualquier clase, y e.compareTo(null) debería lanzar una NullPointerException A pesar de que los rendimientos e.equals(null)false.

Por otro lado Comparator API, menciona nada acerca de lo que debe suceder cuando se comparan null. Considere el siguiente intento de un método genérico que toma un Comparable, y devolver una Comparator por ello que pone null como el elemento mínimo.

static <T extends Comparable<? super T>> Comparator<T> nullComparableComparator() { 
    return new Comparator<T>() { 
     @Override public int compare(T el1, T el2) { 
     return 
      el1 == null ? -1 : 
      el2 == null ? +1 : 
      el1.compareTo(el2); 
     } 
    }; 
} 

Esto nos permite hacer lo siguiente:

List<Integer> numbers = new ArrayList<Integer>(
    Arrays.asList(3, 2, 1, null, null, 0) 
); 
Comparator<Integer> numbersComp = nullComparableComparator(); 
Collections.sort(numbers, numbersComp); 
System.out.println(numbers); 
// "[null, null, 0, 1, 2, 3]" 

List<String> names = new ArrayList<String>(
    Arrays.asList("Bob", null, "Alice", "Carol") 
); 
Comparator<String> namesComp = nullComparableComparator(); 
Collections.sort(names, namesComp); 
System.out.println(names); 
// "[null, Alice, Bob, Carol]" 

Así que las preguntas son:

  • Es éste un uso aceptable de un Comparator, o es violar una regla no escrita respecto comparando null y lanzando NullPointerException?
  • ¿Puede ser una buena idea para tener siquiera para ordenar una List que contienen elementos null, o es que un signo seguro de un error de diseño?
+0

Nota para los demás que tengan problemas para compilar este código: hay un error en javac, pero se compila y se ejecuta en Eclipse. http://stackoverflow.com/questions/2858799/generics-compiles-and-runs-in-eclipse-but-doesnt-compile-in-javac – polygenelubricants

Respuesta

23

Comparable no permite null simplemente porque:

a.compareTo(b) == -b.compareTo(a) 

para todos los objetos a y b donde !a.equals(b). Más específicamente:

a.equals(b) ? b.equals(a) && a.compareTo(b) == 0 && 
        b.compareTo(a) == 0 && a.hashCode() == b.hashCode() 
      : !b.equals(a) && a.compareTo(b) != 0 && 
        a.compareTo(b) == -b.compareTo(a) 

debe evaluar a true para satisfacer los contratos correspondientes.

Así null no está permitido porque no se puede hacer:

null.compareTo(a) 

Comparator es más flexible para la manipulación de null es un problema específico de la implementación. Apoyar o no dependiendo de lo que usted quiere que su Comparator que hacer.

+1

La prueba 'ab == -ba' es convincente, pero prefiero la Argumento de API: 'Comparable' define el orden natural para las instancias de una clase, y' null' simplemente no es una instancia de ninguna clase. ¿Dirigirías el 'null' en la' Lista' en primer lugar, sin embargo? Espero que eso no sea '[subjetivo] '. – polygenelubricants

+0

(Dicha ecuación a.compareTo (b) == -b.compareTo (a) no es necesariamente correcta para todos los tipos. El valor de retorno de compareTo() no necesita representar la diferencia de ningún campo de dos objetos. es una forma en que compareTo() se programa muy a menudo, ¡no es una buena idea! - Una diferencia calculada podría desbordarse y luego dar como resultado un valor positivo/negativo incorrecto. (Mejor, literalmente, devolver -1, 0 o 1 de compareTo() solamente. - No es tan furtivo, pero correcto.)) – Nico

8

¿Alguna vez es una buena idea incluso tener que ordenar una lista que contenga elementos nulos o es una señal segura de un error de diseño?

Conceptualmente, null significa "nada", y no colocar nada en una lista me parece extraño. Además, el contrato de la Lista Java establece que

Algunas implementaciones de listas tienen restricciones sobre los elementos que pueden contener.Por ejemplo, algunas implementaciones prohíben los elementos nulos

por lo que una implementación de lista en Java ni siquiera es necesaria para admitir elementos nulos. En resumen, si no tiene una buena razón para poner nulo en una lista, no lo haga, y si lo hace, pruebe que realmente funciona como se esperaba.

+1

+1 para capturar ese soporte 'nulo' en' Lista' ni siquiera es obligatorio. – polygenelubricants

4

¿Es siempre una buena idea tener incluso a ordenar una lista que contiene elementos nulos, o es que un signo seguro de un error de diseño ?

Bueno, es probable que no tiene sentido para que la lista incluya un objeto nulo, pero tal vez su lista contiene un "objeto de negocio" y se puede clasificar en diferentes propiedades del objeto de negocio, algunos de los cuales pueden contener nulos

Es esto un uso aceptable de un comparador

El BeanComparator le permite ordenar en un hotel fenomenal en un objeto de negocio, incluso si la propiedad contiene nula, por lo que tendría que decir que es una uso aceptable de un Comparador.

+0

¿Qué "BeanComparator"? Esto no forma parte del JDK, no podemos contar con él para probar algo al respecto. – ymajoros

+0

@ymajoros, '¿Qué" BeanComparator "?' El que se encuentra en el enlace. – camickr

+0

que no forma parte del JDK ... Además de ser una mala idea de todos modos (inseguro, interrupciones al refactorizar, etc.). – ymajoros

Cuestiones relacionadas