Salut ci-dessous est ma méthode de comparaison de mon comparateur. Je ne suis pas sûr de ce qui ne va pas. J'ai cherché d'autres questions et réponses intitulées similaires sur le dépassement de capacité de la pile, mais je ne savais pas ce qui n'allait pas avec ma méthode, mais je continue à avoir Java.lang.IllegalArgumentException: la méthode de comparaison viole son contrat général!
Toute aide sera fortement appréciée
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;
}
Ajout de l'exception que je reçois
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)
Votre méthode compare()
est pas transitive . Si A == B
Et B == C
, Alors A
doit être égal à C
.
Considérons maintenant ce cas:
Pour A
, B
et C
, supposons que la méthode containsKey()
renvoie les résultats suivants:
childMap.containsKey(A.getID())
renvoie true
childMap.containsKey(B.getID())
renvoie false
childMap.containsKey(C.getID())
renvoie true
En outre, considérons les commandes pour A.getId()
! = B.getId()
.
Alors,
A
et B
renverraient 0
, Car la condition externe if
sera false
=> A == B
B
et C
renverraient 0
, Car la condition externe if
sera false
=> B == C
Mais, A
et C
pourraient renvoyer -1
Ou 1
, En fonction de votre test dans le bloc if
. Donc, A != C
. Cela viole le principe de transitivité.
Je pense que vous devriez ajouter une condition à l'intérieur de votre bloc else
, qui effectue une vérification similaire à celle du bloc if
.
Je pense que le problème est dans votre cas par défaut. Considérez l'ensemble des nœuds A, B et C, où les ID sont 'a'
, 'b'
Et 'c'
. Pensez en outre que votre childMap
, qui contient les informations de commande relatives, a le contenu suivant:
{ 'a' => 1, 'c' => 3 }
Maintenant, si vous exécutez votre méthode compare
sur A et B, vous retournez 0
, Indiquant que A et B sont équivalents. De plus, si vous comparez B et C, vous retournez toujours 0
. Cependant, si vous comparez A et C, vous retournez -1
, Indiquant que A est plus petit. Ceci viole la propriété de transitivité de le Comparator
contrat :
L'implémenteur doit également s'assurer que la relation est transitive:
((compare(x, y)>0) && (compare(y, z)>0))
Impliquecompare(x, z)>0
.Enfin, l'implémenteur doit s'assurer que
compare(x, y)==0
implique quesgn(compare(x, z))==sgn(compare(y, z))
pour toutz
.
Vous ne pouvez pas traiter les "éléments pour lesquels aucun ordre n'a été attribué" comme ayant la valeur "quelque part vaguement au milieu", car les algorithmes de tri ne savent pas où les placer. Si vous souhaitez conserver cette approche, dans le cas où la valeur ne serait pas présente dans la carte, vous devez affecter une valeur fixe au numéro de référence. quelque chose comme 0
ou MIN_INT
est un choix raisonnable (mais tout choix doit être documenté dans la Javadoc pour compare
!).