switch strings objects different java comparison

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)) implica compare(x, z)>0 .

Finalmente, el implementador debe asegurarse de que compare(x, y)==0 implica que sgn(compare(x, z))==sgn(compare(y, z)) para todos los z .

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í:

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()) devuelve true
  • childMap.containsKey(B.getID()) devuelve false
  • childMap.containsKey(C.getID()) devuelve true

También, considere órdenes para A.getId() ! = B.getId() .

Asi que,

  1. A y B devolverían 0 , como externo if condición fuera false => A == B
  2. B y C devolverían 0 , como externo if condición fuera false => 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 .