¿Por qué mi método de comparación lanza una excepción? ¡El método de comparación viola su contrato general!

Por qué este código

public class SponsoredComparator implements Comparator { public boolean equals(SRE arg0, SRE arg1){ return arg0.getSponsored()==arg1.getSponsored(); } public int compare(SRE object1, SRE object2) { Log.d("SponsoredComparator","object1.getName() == "+ object1.getName()); Log.d("SponsoredComparator","object1.getSponsored() == "+ object1.getSponsored()); Log.d("SponsoredComparator","object2.getName() == "+ object2.getName()); Log.d("SponsoredComparator","object2.getSponsored() == "+ object2.getSponsored()); Log.d("SponsoredComparator","compare return == "+ (object1.getSponsored() && object2.getSponsored() ? 0 : object1.getSponsored() ? -1 : 1)); return object1.getSponsored() && object2.getSponsored() ? 0 : object1.getSponsored() ? -1 : 1; } } 

lanzar esta excepción: ERROR/AndroidRuntime(244): java.lang.IllegalArgumentException: Comparison method violates its general contract!
ERROR/AndroidRuntime(4446): at java.util.TimSort.mergeLo(TimSort.java:743)
ERROR/AndroidRuntime(244): java.lang.IllegalArgumentException: Comparison method violates its general contract!
ERROR/AndroidRuntime(4446): at java.util.TimSort.mergeLo(TimSort.java:743)

El método sre.getSponsored () devuelve un valor booleano.

Gracias.

Sospecho que el problema ocurre cuando ninguno de los valores es patrocinado. Eso devolverá 1 cualquiera que sea la forma en que lo llame, es decir,

 x1.compare(x2) == 1 x2.compare(x1) == 1 

Eso no es válido

Te sugiero que cambies esto:

 object1.getSponsored() && object2.getSponsored() 

a

 object1.getSponsored() == object2.getSponsored() 

en ambos lugares. Probablemente, de hecho, extrajera este método con esta firma en alguna parte:

 public static int compare(boolean x, boolean y) 

y luego llámalo así:

 public int compare(SRE object1, SRE object2) { return BooleanHelper.compare(object1.getSponsored(), object2.getSponsored()); } 

Eso hará que el código sea más claro, IMO.

Supongo que está utilizando JDK 7. Compruebe la siguiente URL:

De http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source

Área: API: Utilidades

Sinopsis: el comportamiento de ordenación actualizado para Arrays y Collections puede arrojar una IllegalArgumentException

Descripción: el algoritmo de clasificación utilizado por java.util.Arrays.sort y (indirectamente) por java.util.Collections.sort se ha reemplazado. La nueva implementación de clasificación puede arrojar una IllegalArgumentException si detecta un Comparable que viola el contrato Comparable . La implementación anterior ignoró silenciosamente tal situación. Si se desea el comportamiento anterior, puede usar la nueva propiedad del sistema, java.util.Arrays.useLegacyMergeSort , para restablecer el comportamiento de mergesort anterior.

Naturaleza de la incompatibilidad: comportamiento

RFE: 6804124

Para obtener información más detallada, consulte la referencia de la base de datos de errores aquí .

El contrato entre equals () y compareTo () es que cuando equals () devuelve verdadero, compareTo () debería devolver 0 y cuando equals () es falso compareTo debería devolver -1 o +1.

Por cierto: supongo que su método compare () no se llama con mucha frecuencia ya que los mensajes de depuración usarán una cantidad significativa de CPU y memoria.

Estuve de acuerdo con todas las respuestas especialmente con jon, pero quiero añadir una cosa adicional: siempre debemos verificar la seguridad nula en el método de comparación para que nuestro método nunca se rompa y es un buen hábito en la progtwigción para la verificación siempre nula. Para más información mira aquí

tal vez solo tengas valores NaN que comparas a través de Collections.sort … esto ha sido un problema para mí y obtuve esa excepción incluso teniendo la implementación correcta del método compare (obj1, obj2)! ¡Mira esto!

Tengo el mismo problema hoy en una aplicación web. Cuatro llamadas que trabajaban en el mismo arreglo intentaron ordenarlo al mismo tiempo, estropeándose efectivamente el uno al otro.