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):
et ici la sortie de Maven (pas correcte):
voici le code (exécutez-le en 1.8 pour réussir, 1.6 pour échec): p>
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>
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>
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 Réponses :
Le problème est dans cette ligne: 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. P> Différentes implémentations JVM peuvent utiliser différents algorithmes de tri, où on présentera ce bogue et l'autre non p> p>
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.
Votre mais si comparèteo () code> est défectueux. Dans le cas où aucun moment de l'objet n'est
null code>, il se résume à
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());
Je pense que j'ai trouvé le problème: Le comparateur renvoya 0 (indiquant l'égalité) qui n'est pas correct: p>
devrait être
au lieu de
et comme indiqué par John mieux mieux: p>
et Java a changé le Trier l'algorithme a> 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 ... p> Retourner cela.Time.Tempore (O.BetTime ())? -1: 1; code> p>
Retourner cela.Time.Tempore (O.BetTime ())? 0: 1; code> p>
retourner cela.time.compareto (o.geTime ()); code> p>
Et si les deux fois sont égaux?
Comme d'autres ont souligné, le problème est dans la dernière ligne de la méthode code> comparète code>.
Depuis Date code> Implements
comparable code>, La solution la plus facile est la suivante: p>
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 ...
Il serait plus facile pour tout le monde si a) votre test utiliserait affirmations b> de sorte qu'un échec conduit à un échec et à b) que vous auriez uniquement i> 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 B> 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.)