0
votes

La méthode Comparer (comparète) renvoie différents résultats dans différents JVM

Je suis perplexe: j'ai écrit un comparateur qui compare les dates. Cependant, lorsque j'exécute le test Junit, il me renvoie différents résultats en fonction de si je l'exécute dans mon IDE ou à Maven ?! Dans mon IDE ça marche et à Maven, ça échoue. Utilisation du même 1,8 JVM dans les deux environnements Toutefois, dans Maven avec 1,6 mode de compatibilité. (Veuillez noter que c'est un projet hérité et utiliser Java.Util.Date est mauvais ... (mais ce n'est pas le point maintenant)

Voici la sortie de l'IDE (correct): Anniversaire [Id = quatre, Time = Thu Sep 23 20:54:24 CEST 2010] Anniversaire [id = six, heure = mercredi 01 01:01:01 CET 2012] Anniversaire [id = cinq, heure = mercredi 01 01:01:02 CET 2012] Anniversaire [id = trois, heure = mar jan 08 17:30:43 CET 2019] Anniversaire [id = un,] Anniversaire [id = deux,] code> p>

et ici la sortie de Maven (pas correcte): Anniversaire [Id = quatre, Time = Thu Sep 23 20:54:24 CEST 2010] Anniversaire [id = trois, heure = mar jan 08 17:26:25 CET 2019] Anniversaire [id = cinq, heure = mercredi 01 01:01:02 CET 2012] Anniversaire [id = six, heure = mercredi 01 01:01:01 CET 2012] Anniversaire [id = un,] Anniversaire [id = deux,] code> p>

voici le code (exécutez-le en 1.8 pour réussir, 1.6 pour échec): p>

import java.util.Date;

public class Birthday implements Comparable<Birthday>{

    private String id;
    private Date time;

    public String getId() {
        return this.id;
    }
    public Birthday(String id, Date time) {
        this.id=id;
        this.time=time;
    }
    public Date getTime() {
        return this.time;
    }
    public void setTime(Date time) {
        this.time = time;
    }
    @Override
    public int compareTo(Birthday o) {   
        //if both are null return 0 for equals
        if(this.time==null && o.getTime()==null) {
            return 0;
        }

        //null birthdays should always be last
        if(this.time==null) {
            return 1;
        }
        if(o.getTime() == null) {
            return -1;            
        }
        return this.time.before(o.getTime()) ? 0 : 1;
    }

    @Override
    public String toString() {
        return this.id+" "+this.time;
    }
}

@Test
public void testTime() {
    Birthday info1 = new Birthday("one",null);
    Birthday info2 = new Birthday("two", null);
    Birthday info3 = new Birthday("three",new Date());
    Birthday info4 = new Birthday("four",new Date(110,8,23,20,54,24));
    Birthday info5 = new Birthday("five",new Date(112,1,1,1,1,2));
    Birthday info6 = new Birthday("six",new Date(112,1,1,1,1,1));

    ArrayList<Birthday> dates = new ArrayList<Birthday>();
    dates.add(info1);
    dates.add(info2);
    dates.add(info4);
    dates.add(info3);
    dates.add(info5);
    dates.add(info6);

    Collections.sort(dates);

    for(Birthday bs: dates) {
        System.out.println(bs);
    }

    Assert.assertEquals(info4, dates.get(0));
    Assert.assertEquals(info6, dates.get(1));
    Assert.assertEquals(info7, dates.get(2));
    Assert.assertEquals(info5, dates.get(3));
    Assert.assertEquals(info3, dates.get(4));
    Assert.assertEquals(info1, dates.get(5));
    Assert.assertEquals(info2, dates.get(6));
}


4 commentaires

Il serait plus facile pour tout le monde si a) votre test utiliserait affirmations de sorte qu'un échec conduit à un échec et à b) que vous auriez uniquement cas de défaillance de votre contribution ( ou dire: un échec, un passage)


J'avais affirmé dans le test d'origine et c'est comme ça que j'ai détecté le problème en premier lieu. Mais pour la lisibilité ici, je me suis retrouvé ...


Il y a toujours exemple de reproductible minimal . Pourquoi s'embêter avec le tri, ou demander aux gens de comparer les résultats de Tostring () pour comprendre ce qui se passe. Aidez-vous également à vous déboguer. C'est en fait ce que vous voulez Tests unitaires pour: Le chemin le plus rapide menant à un problème, vous pouvez donc vous transformer en débogueur et comprendre ce qui se passe ....


Oui, je sais mcv - c'est pourquoi j'ai ajouté le code en premier lieu. Mais la lisibilité est également un facteur important. Plus le code est le moins de code ... et merci pour les astuces, mais le code lui-même est complet (concernant des exemples de réussite / défaillance). Il doit juste être exécuté dans différentes JVM ... (mais j'ai ajouté un indice pour ça.)


4 Réponses :


3
votes

Le problème est dans cette ligne: xxx

Si ce poste est avant le temps des autres, ils sont égaux. Ce n'est pas réflexif, vous cassez donc les exigences de comparèteo.

Différentes implémentations JVM peuvent utiliser différents algorithmes de tri, où on présentera ce bogue et l'autre non


4 commentaires

Oui en effet - j'ai trouvé le problème après un peu d'analyse ... mais l'effet était assez déroutant en premier lieu :-)


Oui, les exigences de rupture des opérations relationnelles peuvent être assez intéressantes ...


juste obtenir la valeur longue et les soustraire. ordre inverse des opérandes d'inverser les commandes.


@MAVRIKSCC Depuis que les valeurs de date sont comparables, utilisez CareeTo () d'obtenir des valeurs longues et de soustraire.



1
votes

Votre comparèteo () code> est défectueux. Dans le cas où aucun moment de l'objet n'est null code>, il se résume à xxx pré>

mais si o.time.before (this.gettime ()) code>? Votre comparèteo () code> doit renvoyer de manière fiable -1 dans ce cas, mais elle renvoie 0. java.util.date code> a un ordre naturel, que vous pourriez aussi bien utiliser que tant que vous comptez sur cette classe en premier lieu: P>

        return this.time.compareTo(o.getTime());


0 commentaires

1
votes

Je pense que j'ai trouvé le problème: Le comparateur renvoya 0 (indiquant l'égalité) qui n'est pas correct:

devrait être Retourner cela.Time.Tempore (O.BetTime ())? -1: 1;

au lieu de Retourner cela.Time.Tempore (O.BetTime ())? 0: 1;

et comme indiqué par John mieux mieux:

retourner cela.time.compareto (o.geTime ());

et Java a changé le Trier l'algorithme dans JDK 1.7 qui gère probablement des valeurs égales différemment. Donc, cela est venu ensemble dans cet intéressant casse-tête ...


1 commentaires

Et si les deux fois sont égaux?



3
votes

Comme d'autres ont souligné, le problème est dans la dernière ligne de la méthode comparète .

Depuis Date Implements comparable , La solution la plus facile est la suivante: xxx


1 commentaires

Si votre rythme continue comme ça, vous allez bientôt me remettre à nouveau ;-) ... et vous atteindrez 100k avant. Et puis je vous aide même à vous aider ...