Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2298 connectés 

  FORUM HardWare.fr
  Programmation
  Java

  compareTo() vs equals()

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

compareTo() vs equals()

n°2035553
leonhard
Posté le 12-11-2010 à 09:03:42  profilanswer
 

Bonjour
 
Je suis en train de faire un petit programme qui utilise des objets de type BigInteger. Parfois je dois comparer si deux nombres sont égaux. Je me suis demandé si (dans le cas spécifique ou je garantis que les deux objets que je compare sont bien des BigInteger), il y a un avantage à utiliser la méthode equals() plutôt que la méthode compareTo(). Est-ce que l'une est plus efficace que l'autre ?
 
En regardant le code j'aurais tendance à penser que la méthode equals() est un petit peu plus rapide parce qu'elle ne doit pas s'occuper de l'ordre, mais vérifier s'il y a une différence. Qu'en pensez-vous ?
 
 
D'avance merci de votre aide et de vos conseils.
 

mood
Publicité
Posté le 12-11-2010 à 09:03:42  profilanswer
 

n°2035558
olivthill
Posté le 12-11-2010 à 10:03:15  profilanswer
 

D'après la doc, par exemple http://leepoint.net/notes-java/dat [...] jects.html , il semble que equals() soit plus primitif que compareTo(), et donc soit plus rapide, mais c'est à vérifier par des mesures. En matière d'optimisation, il vaut toujours mieux mesurer que spéculer.
 
J'en pense que, si la vitesse est un critère important, on peut écrire ce bout de programme en C ou en assembleur, au lieu de Java, car Java est forcément plus lent, à cause de la couche de la JVM et des objets. En général, on cherche les bugs plutôt que les gains de micro-secondes. Une règle général dit que les opérations en mémoire sont très rapides, celles avec des I/O sur disque sont plus lentes, et celles sur le réseau sont lentes aussi, donc il faut optimiser ces deux dernières sortes d'opération, plutôt que les opérations locales.

n°2035652
masklinn
í dag viðrar vel til loftárása
Posté le 12-11-2010 à 14:24:38  profilanswer
 

equals dit que tu veux savoir si deux objets sont égaux (et renvoie un booléen), compareTo non.

 

À ton avis, est-il plus lisible de voir if(a.equals(b)) ou if(a.compareTo(b) == 0).

 

Tu as ta réponse sur lequel utiliser. Parler des performances de equals et compareTo, surtout sur les types de la stdlib, c'est de la branlette de bas étage.


Message édité par masklinn le 12-11-2010 à 14:25:09

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°2035857
sircam
I Like Trains
Posté le 14-11-2010 à 10:38:48  profilanswer
 

olivthill a écrit :

En matière d'optimisation, il vaut toujours mieux mesurer que spéculer.


suivi d'un malheureux :
 

olivthill a écrit :

car Java est forcément plus lent


 [:serumm:5]  


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
n°2035859
sircam
I Like Trains
Posté le 14-11-2010 à 10:53:03  profilanswer
 

mask> Je dirais que c'est moins une question de lisibilité que de sémantique de l'opération.
 
Pour Integer, equals est consistent avec l'ordre naturel et la question se réduit à la lisibilité et/ou aux performances, mais ce n'est pas forcément le cas avec toutes les classes.
 
On peut parfois avoir :
 

Code :
  1. !a.equals(b) && a.compareTo(b) == 0


 
La sémantique doit primer sur la lisibilité et les éventuelles différences de perf si on veut un résultat correct!


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
n°2035917
olivthill
Posté le 14-11-2010 à 22:53:06  profilanswer
 

Citation :

suivi d'un malheureux :
[:serumm:5]  


Vous profitez du laxisme des modérateurs.
 
Pourquoi intervenir pour une critique négative ? Et surtout une critique sans aucun argument ? C'est un coup de pied lâche et gratuit.
 
En plus, c'est faux, Java est plus que lent que le C.
 
Moi, je suis sérieux, j'argumente, par exemple en citant un extrait de http://info-rital.developpez.com/t [...] /pourquoi/ :

Citation :

Les programmes utilisant les premières versions de la JVM étaient entre 20 et 40 fois plus lents que leur équivalents en C par exemple. Tout simplement car le Java Byte Code était interpreté par la machine virtuelle. Or par définition, une code interprété est plus lent qu'un code natif. Mais c'était en 1993...A partir de 1995, Sun a incorporé la technologie HotSpot, un compilateur JIT (Just-In-Time) dans ses JVM. Il s'agit en fait d'une autre étape de la compilation, mais dont vous n'avez pas à vous occuper.  
La JVM repère les morceaux de code très utilisés et les compile en code natif, donc qui ne passe plus par une interpretation et qui est donc forcement plus rapide. Cette technologie devient de plus en plus performante à chaque nouvelle version. De plus vous pouvez lancement une compilation complète de l'application en code natif, donc il n'y aura plus d'interpretation de code. Cependant le temps de lancement sera bien plus long.  
 
De nos jours, sur une machine correcte, une programme Java est en moyenne entre 1.1 et 1.3 plus lent que son équivalent en C++.
 
Java consomme plus de RAM que les autres langages, même pour un petit programme. C'est pour ça que généralement plus de 256Mo de RAM sont recommandés mais on peut bien sûr faire avec sans trop de problèmes avec beaucoup moins de RAM. De toute façon de nos jours, 256 Mo est souvent trop peu et peut brider le reste du PC si il est puissant. De plus, il existe deux versions officielles de la JVM de Sun, mais c'est transparent pour l'utilisateur, et elles seront sûrement dans le future, réunies en une seule. Il y a une JVM "client", plus rapide à lancer, qui consomme moins de ressource, mais moins performante, c'est celle là qui est lancée par défaut et une JVM "server", plus longue à démarrer, qui consomme plus de RAM, mais qui est beaucoup plus rapide. Cela s'explique par le fait que la JVM "server" effectue bien plus d'optimisations.


 

n°2036033
exhortae
Membre du Cartel des Médecins
Posté le 15-11-2010 à 12:58:39  profilanswer
 

Un article de 2006

n°2036041
phnatomass
Je m'empare de ton esprit !!
Posté le 15-11-2010 à 13:38:46  profilanswer
 

Que l'exécution du programme en langage Java soit un peu plus lent que son homologue développé en C/C++ est une réalité dans de nombreux cas.
Par conte le propos est que certaines prétendues optimisations feront gagner des miettes en terme de performance mais rendront le code difficilement lisible.

n°2036053
gilou
Modérateur
Modzilla
Posté le 15-11-2010 à 14:09:44  profilanswer
 

Le fait qu'en moyenne un programme java soit plus lent qu'un programme C++, ce n'est qu'un effet de bord du niveau moyen d'un programmeur Java vis à vis du niveau moyen d'un programmeur C++, non? [:biiij:1]  
 :sol:  
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2036083
esox_ch
Posté le 15-11-2010 à 16:30:16  profilanswer
 

C'est clair, suffi de voir le nombre de boulets qui posent dans la cat C/C++ parce qu'ils ont "perdu" leurs pointeurs pour s'en rendre compte :lol:


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
mood
Publicité
Posté le 15-11-2010 à 16:30:16  profilanswer
 

n°2036180
sircam
I Like Trains
Posté le 16-11-2010 à 08:56:57  profilanswer
 

Bande de trolls gluants... Mais que fait la modération? [:pingouino]


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
n°2036201
Bidem
Posté le 16-11-2010 à 10:20:10  profilanswer
 

Sinon pour en revenir à la question d'origine :
 

Code :
  1. public static void main(String[] args) {
  2.   // Construction d'un tableau contenant des BigInteger alléatoires
  3.   BigInteger[] lstBi = new BigInteger[10000];
  4.   long debut= System.currentTimeMillis();
  5.   for (int i = 0; i < lstBi.length; i++) {
  6.     String i1 = Long.toString((long) (Math.random() * Long.MAX_VALUE));
  7.     lstBi[i] = new BigInteger(i1+i1+i1+i1);
  8.   }
  9.   System.out.println("init : " + (System.currentTimeMillis() - debut) + " ms" );
  10.   // On compare les éléments 2 à 2 en utilisant compareTo
  11.   debut= System.currentTimeMillis();
  12.   for (int i = 0; i < lstBi.length; i++) {
  13.     for (int j = lstBi.length - 1; j >= 0; j--) {
  14.       if (lstBi[i].compareTo(lstBi[j])==0);
  15.     }
  16.   }
  17.   System.out.println("compareTo : " + (System.currentTimeMillis() - debut) + " ms" );
  18.   // même chose avec equals
  19.   debut= System.currentTimeMillis();
  20.   for (int i = 0; i < lstBi.length; i++) {
  21.     for (int j = lstBi.length - 1; j >= 0; j--) {
  22.       if (lstBi[i].equals(lstBi[j]));
  23.     }
  24.   }
  25.   System.out.println("equals : " + (System.currentTimeMillis() - debut) + " ms" );
  26.   // Profit
  27. }


 

Code :
  1. init : 94 ms
  2. compareTo : 7906 ms
  3. equals : 6875 ms


 
En conclusion, equals est plus performant et est préférable du point de vue de la lisibilité du code et de la sémantique.

Message cité 3 fois
Message édité par Bidem le 16-11-2010 à 10:21:50
n°2036204
masklinn
í dag viðrar vel til loftárása
Posté le 16-11-2010 à 10:25:25  profilanswer
 

Bidem a écrit :

Code :
  1. init : 94 ms
  2. compareTo : 7906 ms
  3. equals : 6875 ms
 

En conclusion, equals est plus performant et est préférable du point de vue de la lisibilité du code et de la sémantique.


init : 127 ms
compareTo : 1722 ms
equals : 3098 ms


> java -version                                  
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04-307-10M3261)
Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03-307, mixed mode)


Et si je remplace l'init par:

Code :
  1. Random rng = new Random();
  2.        long debut= System.currentTimeMillis();
  3.        for (int i = 0; i < lstBi.length; i++) {
  4.            lstBi[i] = new BigInteger(String.format("%d%d%d%d",
  5.                                                    Math.abs(rng.nextLong()),
  6.                                                    Math.abs(rng.nextLong()),
  7.                                                    Math.abs(rng.nextLong()),
  8.                                                    Math.abs(rng.nextLong())));
  9.        }


init : 449 ms
compareTo : 827 ms
equals : 979 ms


Message édité par masklinn le 16-11-2010 à 10:36:49

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°2036246
Bidem
Posté le 16-11-2010 à 11:59:01  profilanswer
 

J'ai réessayé avec ton init et ça ne change pas grand chose à mes résultats :
 

Code :
  1. C:\>java -version
  2. java version "1.6.0_22"
  3. Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
  4. Java HotSpot(TM) Client VM (build 17.1-b03, mixed mode, sharing)


NB : PC pas très puissant sur un Windows 32 bits
 

Code :
  1. init : 312 ms
  2. compareTo : 5047 ms
  3. equals : 4594 ms


 
On peut donc supposer que ça vient du fait que tu ais une JVM 64 bits.
Je réessayerai ce soir sur un PC plus puissant (32 bits aussi) mais je doute que ça puisse inverser la tendance.

n°2036252
masklinn
í dag viðrar vel til loftárása
Posté le 16-11-2010 à 12:04:55  profilanswer
 

Bidem a écrit :

On peut donc supposer que ça vient du fait que tu ais une JVM 64 bits.


Yup, ça a l'air d'être ça:

> java -version                                    
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04-307-10M3261)
Java HotSpot(TM) Client VM (build 17.1-b03-307, mixed mode)                            
masklinn@yuricon> java Test                                        
init : 209 ms
compareTo : 2301 ms
equals : 1632 ms
> java -server Test                                
init : 518 ms
compareTo : 1127 ms
equals : 1204 ms
>
> java -version                                    
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04-307-10M3261)
Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03-307, mixed mode)
> java Test                                        
init : 471 ms
compareTo : 878 ms
equals : 1022 ms
> java -server Test                                
init : 447 ms
compareTo : 1075 ms
equals : 1530 ms


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°2036280
esox_ch
Posté le 16-11-2010 à 14:02:27  profilanswer
 

A mon avis c'est pas tant le fait que ce soit 64 bits que la différence entre les optimisations internes JVM Client VS JVM Server


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
n°2036295
masklinn
í dag viðrar vel til loftárása
Posté le 16-11-2010 à 14:11:44  profilanswer
 

esox_ch a écrit :

A mon avis c'est pas tant le fait que ce soit 64 bits que la différence entre les optimisations internes JVM Client VS JVM Server


Quoi qu'ils dise, ça fait tourner la JVM client par défaut, j'ai testé en forçant `-client`, d'où le test en `-server` derrière.


Message édité par masklinn le 16-11-2010 à 14:12:08

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°2036743
sircam
I Like Trains
Posté le 17-11-2010 à 20:59:57  profilanswer
 

Bidem a écrit :


En conclusion, equals est plus performant et est préférable du point de vue de la lisibilité du code et de la sémantique.


C'est faux pour la partie en gras. Avec Integer, cela ne fait sans doute pas de différence, mais avec d'autres types, il faut utiliser compareTo pour vérifier une relation d'ordre.
 
 [:pingouino]  


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
n°2036751
masklinn
í dag viðrar vel til loftárása
Posté le 17-11-2010 à 21:24:03  profilanswer
 

sircam a écrit :


C'est faux pour la partie en gras. Avec Integer, cela ne fait sans doute pas de différence, mais avec d'autres types, il faut utiliser compareTo pour vérifier une relation d'ordre.
 
 [:pingouino]  


Sauf qu'on veut pas une relation d'ordre là, on veut juste une égalité.


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°2036762
sircam
I Like Trains
Posté le 17-11-2010 à 22:20:00  profilanswer
 

masklinn a écrit :


Sauf qu'on veut pas une relation d'ordre là, on veut juste une égalité.


C'est kif-kif dans le cas de BigInteger parce que equals() est consistant avec l'ordre naturel, mais ce n'est pas généralisable à tous les types numériques. C'est sur ce piège que portais ma remarque avec certains types infâmes :


a.compareTo(b) == 0 -> true
a.equals(b) -> false


dans ce cas, seul compareTo() peut vérifier une égalité de valeur numérique et possède la sémantique correcte.
 
Je trouve ça moins confortable d'utiliser equals() avec certains types parce que ça tombe bien mais compareTo() avec d'autres parce qu'on n'a pas le choix, alors que compareTo() est correct partout. Mais bon, hein, equals est très bien ici. :o


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
n°2036764
masklinn
í dag viðrar vel til loftárása
Posté le 17-11-2010 à 22:23:04  profilanswer
 

sircam a écrit :


C'est kif-kif dans le cas de BigInteger parce que equals() est consistant avec l'ordre naturel, mais ce n'est pas généralisable à tous les types numériques. C'est sur ce piège que portais ma remarque avec certains types infâmes :


a.compareTo(b) == 0 -> true
a.equals(b) -> false


dans ce cas, seul compareTo() peut vérifier une égalité de valeur numérique et possède la sémantique correcte.


Ouais enfin si compareTo est défini et equals pas, faut pas utiliser compareTo, faut défoncer le mec qui a écrit la classe à coup de batte.


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°2036775
sircam
I Like Trains
Posté le 17-11-2010 à 22:47:16  profilanswer
 

masklinn a écrit :


Ouais enfin si compareTo est défini et equals pas, faut pas utiliser compareTo, faut défoncer le mec qui a écrit la classe à coup de batte.


Beh tu peux avoir equals et compareTo parfaitement définis, et les deux relations que j'ai décrites (ordre naturel pas consistant avec equals)... le tout livré dans java.math.
 
Y'a pas forcément moyen de faire autrement dans certains cas.
[:alph-one]


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
n°2037412
leonhard
Posté le 21-11-2010 à 10:23:47  profilanswer
 

Bidem a écrit :

Sinon pour en revenir à la question d'origine :
 

Code :
  1. public static void main(String[] args) {
  2.   // Construction d'un tableau contenant des BigInteger alléatoires
  3.   BigInteger[] lstBi = new BigInteger[10000];
  4.   long debut= System.currentTimeMillis();
  5.   for (int i = 0; i < lstBi.length; i++) {
  6.     String i1 = Long.toString((long) (Math.random() * Long.MAX_VALUE));
  7.     lstBi[i] = new BigInteger(i1+i1+i1+i1);
  8.   }
  9.   System.out.println("init : " + (System.currentTimeMillis() - debut) + " ms" );
  10.   // On compare les éléments 2 à 2 en utilisant compareTo
  11.   debut= System.currentTimeMillis();
  12.   for (int i = 0; i < lstBi.length; i++) {
  13.     for (int j = lstBi.length - 1; j >= 0; j--) {
  14.       if (lstBi[i].compareTo(lstBi[j])==0);
  15.     }
  16.   }
  17.   System.out.println("compareTo : " + (System.currentTimeMillis() - debut) + " ms" );
  18.   // même chose avec equals
  19.   debut= System.currentTimeMillis();
  20.   for (int i = 0; i < lstBi.length; i++) {
  21.     for (int j = lstBi.length - 1; j >= 0; j--) {
  22.       if (lstBi[i].equals(lstBi[j]));
  23.     }
  24.   }
  25.   System.out.println("equals : " + (System.currentTimeMillis() - debut) + " ms" );
  26.   // Profit
  27. }


 

Code :
  1. init : 94 ms
  2. compareTo : 7906 ms
  3. equals : 6875 ms


 
En conclusion, equals est plus performant et est préférable du point de vue de la lisibilité du code et de la sémantique.


 
Voilà un message très intéressant et je te remercie d'avoir pris le temps de répondre à ma question avec autant d'arguments.  
 
J'ai lancé ton test sur mon boulier et j'ai des résultats similaires en ce qui concerne les performances  (java 1.6.21 64 bits). D'ailleurs la différence entre equals() et compareTo() augmente avec le nombre de comparaisons, ce qui prouve que ce n'est pas un simple offset. Cependant, l'argument sémantique soutenu par certain me semble aussi pertinent. Je suis convaincu que la lisibilité (et donc la capacité du programme a être vérifié) prime sur la performance (à quelque rares exceptions près). Qui s'intéresse à un programme rapide qui retourne des conneries ?  
 
Merci encore pour tes explications éclairantes !

n°2037413
leonhard
Posté le 21-11-2010 à 10:33:08  profilanswer
 

sircam a écrit :

mask> Je dirais que c'est moins une question de lisibilité que de sémantique de l'opération.
 
Pour Integer, equals est consistent avec l'ordre naturel et la question se réduit à la lisibilité et/ou aux performances, mais ce n'est pas forcément le cas avec toutes les classes.
 
On peut parfois avoir :
 

Code :
  1. !a.equals(b) && a.compareTo(b) == 0


 
La sémantique doit primer sur la lisibilité et les éventuelles différences de perf si on veut un résultat correct!


 
 
Mon inculture en informatique est grande je le reconnais, aussi je n'arrive pas à imaginer d'exemple ou les deux expressions booléennes ci-dessus seraient vraies en même temps. Accepterais-tu de m'en dire un peu plus s.t.p. ? Dans quel cas pourrait-on avoir a.compareTo(b) == 0 et pas a.equals(b) ? Sur des ensemble pour lesquels on n'aurait qu'un ordre partiel ?
 
D'avance merci pour tes explications éventuelles.

n°2037505
Bidem
Posté le 21-11-2010 à 23:30:51  profilanswer
 

leonhard a écrit :


 
 
Mon inculture en informatique est grande je le reconnais, aussi je n'arrive pas à imaginer d'exemple ou les deux expressions booléennes ci-dessus seraient vraies en même temps. Accepterais-tu de m'en dire un peu plus s.t.p. ? Dans quel cas pourrait-on avoir a.compareTo(b) == 0 et pas a.equals(b) ? Sur des ensemble pour lesquels on n'aurait qu'un ordre partiel ?
 
D'avance merci pour tes explications éventuelles.


 
 
Un exemple tout simple : imagine que tu as une classe Voiture et que tu décides de définir leur définir leur ordre par rapport à l'année de production.
 
a = New Voiture("Peugeot 206", 2010);
b = New Voiture("Citroen Xara", 2010);
 
Taadaaa !

n°2038960
sircam
I Like Trains
Posté le 29-11-2010 à 09:08:02  profilanswer
 

Bidem a écrit :


 
 
Un exemple tout simple : imagine que tu as une classe Voiture et que tu décides de définir leur définir leur ordre par rapport à l'année de production.
 
a = New Voiture("Peugeot 206", 2010);
b = New Voiture("Citroen Xara", 2010);
 
Taadaaa !


Ou plus évident encore : deux instances de BigDecimal avec des précisions différentes, par exemple 4.0 et 4.00!


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Java

  compareTo() vs equals()

 

Sujets relatifs
Equals[.Net 2 CLR] relation entre GetHashCode() et Equals()
Imposer une methode Equals pour une recherche dans une List[JAVA]trier un tableau sans comparable ni compareTo
NullPointerException avec la methode equals et split !!!! [Résolu]Stress sur un TreeSet ! objets non equals removés
[Java] equals() = bizarre 
Plus de sujets relatifs à : compareTo() vs equals()


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR