La méthode de comparaison viole son contrat général! Java 7 seulement

je sais que cela a été un problème depuis un certain temps maintenant, et j'ai vérifié toutes les réponses précédemment que je pouvais obtenir, mais encore celui-ci ne fonctionne pas.

l'objet "crew" représente les membres d'équipage avec grades et autres éléments. La comparaison doit être faite en comparant 'assigned_rank', une valeur int, et si cette valeur est égale dans les deux cas, alors 'is_trainer', un booléen, devrait faire la différence.

cette méthode fonctionnait bien tant qu'elle fonctionnait avec java < 7. Mais depuis Java 7 je continue à obtenir celui-ci:

java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeLo(ComparableTimSort.java:714)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:451)
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:376)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:182)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
at java.util.Collections.sort(Collections.java:155)
at dormas_flightlog.Query.getCrew(Query.java:714)

Voici la source, où certaines parties potentiellement dangereuses ont déjà été commentées, mais cela ne fonctionne toujours pas:

public class crew implements Serializable, Comparable<crew> {

private static final long serialVersionUID = 36L;
private int flightID = 0;
private int assigned_rank = 25;
private boolean is_trainer = false;
...


@Override
public int compareTo(crew him) {

    int myRank = this.getAssigned_rank();
    int hisRank = him.assigned_rank;

    if (this == him) {
        return 0;
    }
    if (myRank > hisRank) {
        return 1;
    }
    if (myRank < hisRank) {
        return -1;
    }
    if (myRank == hisRank) {
//            if (is_trainer && !o.is_trainer) {
//                i = 1;
//            }
//            if (!is_trainer && o.is_trainer) {
//                i = -1;
//            }
//            if (is_trainer && o.is_trainer) {
//                i = 0;
//            }
//            if (!is_trainer && !o.is_trainer) {
//                i = 0;
//            }
        return 0;
    }

    return 0;
}

@Override
public int hashCode() {
    int hash = 7;
    hash = 31 * hash + this.assigned_rank;
    hash = 31 * hash + (this.is_trainer ? 1 : 0);
    return hash;
}

@Override
public boolean equals(Object o) {

    if (this == o) {
        return true;
    }


    int myRank = this.getAssigned_rank();
    int hisRank = 0;

    if (o instanceof crew) {
        crew him = (crew) o;
        hisRank = him.assigned_rank;
    } else {
        return false;
    }

    if (myRank > hisRank) {
        return false;
    }
    if (myRank < hisRank) {
        return false;
    }
    if (myRank == hisRank) {
//            if (is_trainer && !o.is_trainer) {
//                i = 1;
//            }
//            if (!is_trainer && o.is_trainer) {
//                i = -1;
//            }
//            if (is_trainer && o.is_trainer) {
//                i = 0;
//            }
//            if (!is_trainer && !o.is_trainer) {
//                i = 0;
//            }
        return true;
    }

    return false;
}

}

implémenter equals () était juste un essai pour résoudre ce problème. L'exception donnée vient avec ou sans égaux (). Je ne vois pas comment la méthode compareTo viole son contrat. Toute aide est grandement apprécier....un jour, ce code doit travailler avec java 7 et je ne sais pas comment... Merci

32
demandé sur Marek Sebera 2011-10-21 16:42:18

4 réponses

voir ceci:

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

Zone: API: Utilities Synopsis: mise à jour du comportement de tri pour les tableaux et Les Collections peuvent donner lieu à une exception D'Illégalargument

Description: algorithme de tri utilisé par java.util.Tableau.de tri et de (indirectement) par java.util.Collection.tri a été remplacé. Nouvelle l'implémentation de sort peut lancer une exception D'ArgumentException illégale si elle détecte un Comparable qui viole le contrat Comparable. La précédente la mise en œuvre n'a pas tenu compte de cette situation. Si la précédente comportement est souhaité, vous pouvez utiliser le nouveau système la propriété java.util.Tableau.useLegacyMergeSort, pour restaurer mergesort comportement.

la Nature de l'Incompatibilité: comportemental

RFE: 6804124

pour plus d'informations, voir la base de données des bogues référence ici .

44
répondu naresh 2015-04-01 03:33:26

peut-être que vous venez d'avoir NaN valeurs que vous comparez à travers Collections.sort(...) , cela a été un problème pour moi et j'ai cette exception même avoir la bonne mise en œuvre de compare(obj1, obj2) méthode! Vérifier que!

8
répondu Ahmed Ashour 2017-05-02 10:55:16

j'ai pu résoudre cette erreur car c'était un bug dans jdk7.

ici j'ai trouvé la solution:

" la méthode de comparaison viole son contrat général!"- TimSort et GridLayout

J'ai simplement dû ajouter le

JAVA_OPTS="$JAVA_OPTS -Djava.util.Arrays.useLegacyMergeSort=true"

à mon jboss

6
répondu cabaji99 2017-05-23 11:54:53

malheureusement, aucune des solutions ne fonctionne pour Android. TimSort est utilisé en profondeur dans le ViewGroup D'Android relatif à addChildrenForAccessibility qui apparaît sous Java 7 & 8. Aucun code utilisateur n'est impliqué dans aucune comparaison.

D'autres rapports, il s'agit D'avoir relativement peu de points qui se chevauchent, comme c'est généralement le cas. Par exemple, un TextView qui apparaît sur une Image ou deux objets au même endroit, où vous définissez uniquement visible à la fois. https://code.google.com/p/android/issues/detail?id=55933

Je n'ai trouvé aucun moyen de contourner le bug. Vous ne pouvez pas définir une option-Djava dans Android Studio ou Eclipse (au moins que je pourrais trouver). Forcer L'utilisation de Java 1.6 devrait fonctionner, mais ne fonctionne pas. Il semble que les nouvelles tablettes et téléphones de feu D'Amazon sont beaucoup plus sensibles à ce bug que d'autres appareils.

il y a des rumeurs que Java 9 aura une correction telle qu'une option d'exécution qui fonctionne, mais avec un bug qui existe depuis des années, je doute qu'il soit jamais corrigé - surtout compte tenu de l'animosité entre Oracle et Google. Tout oui, peut-être que le bug est vraiment profond dans le code Android et devrait être corrigé. Avec plus d'un milliard d'appareils, ce n'est pas une solution viable pour tous les appareils existants.

0
répondu Frank 2017-03-08 22:50:08