strings - string java
java.lang.IllegalArgumentException: el método de comparación infringe su contrato general (2)
Creo que el problema está en su caso por defecto. Considere el conjunto de nodos A, B y C, donde los identificadores son ''a''
, ''b''
y ''c''
. Considere además que su childMap
, que contiene la información relativa al pedido, tiene los siguientes contenidos:
{ ''a'' => 1, ''c'' => 3 }
Ahora, si ejecuta su método de compare
en A y B, devuelve 0
, lo que indica que A y B son equivalentes. Además, si comparas B y C, todavía devuelves 0
. Sin embargo, si compara A y C, entonces devuelve -1
, lo que indica que A es más pequeño. Esto viola la propiedad de transitividad del contrato del Comparator
:
El implementador también debe asegurarse de que la relación sea transitiva:
((compare(x, y)>0) && (compare(y, z)>0))
implicacompare(x, z)>0
.Finalmente, el implementador debe asegurarse de que
compare(x, y)==0
implica quesgn(compare(x, z))==sgn(compare(y, z))
para todos losz
.
No puede tratar "los artículos que no tienen una orden asignada" como si tuvieran el valor "en algún lugar vagamente en el medio", ya que los algoritmos de clasificación no saben dónde colocarlos. Si desea permanecer con este enfoque, entonces, en el caso de que el valor no esté presente en el mapa, debe asignar un valor fijo como número de pedido; Algo así como 0
o MIN_INT
es una opción razonable (¡pero cualquier opción debe documentarse en el Javadoc para compare
!).
Esta pregunta ya tiene una respuesta aquí:
- Error de Java: el método de comparación infringe las respuestas del contrato general 7
Hola a continuación es mi método de comparación de mi comparador. No estoy seguro que está mal. Busqué otras preguntas y respuestas tituladas similares en el desbordamiento de pila, pero no estoy seguro de lo que está mal con mi método, pero sigo recibiendo java.lang.IllegalArgumentException: ¡El método de comparación viola su contrato general!
cualquier ayuda será apreciada
public int compare(Node o1, Node o2)
{
HashMap<Integer,Integer> childMap = orderMap.get(parentID);
if(childMap != null && childMap.containsKey(o1.getID()) &&
childMap.containsKey(o2.getID()))
{
int order1 = childMap.get(o1.getID());
int order2 = childMap.get(o2.getID());
if(order1<order2)
return -1;
else if(order1>order2)
return 1;
else
return 0;
}
else
return 0;
}
Agregando la excepción que estoy recibiendo
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:747)
at java.util.TimSort.mergeAt(TimSort.java:483)
at java.util.TimSort.mergeCollapse(TimSort.java:410)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)
Su método de compare()
no es transitivo . Si A == B
y B == C
, entonces A
debe ser igual a C
Ahora considere este caso:
Para A
, B
y C
, suponga que el método containsKey()
devuelve estos resultados:
-
childMap.containsKey(A.getID())
devuelvetrue
-
childMap.containsKey(B.getID())
devuelvefalse
-
childMap.containsKey(C.getID())
devuelvetrue
También, considere órdenes para A.getId()
! = B.getId()
.
Asi que,
-
A
yB
devolverían0
, como externoif
condición fuerafalse
=>A == B
-
B
yC
devolverían0
, como externoif
condición fuerafalse
=>B == C
Pero, A
y C
, podrían devolver -1
, o 1
, según su prueba dentro del bloque if
. Entonces, A != C
Esto viola el principio de transitividad.
Creo que debería agregar alguna condición dentro de su bloque else
, que realiza una comprobación similar a la forma en que lo hace en el bloque if
.