tl; dr mon avis est d'utiliser un unaire +
pour déclencher le déballage sur l'un des opérandes lors de la vérification de l'égalité des valeurs, et d'utiliser simplement les opérateurs mathématiques dans le cas contraire. La justification est la suivante:
Il a déjà été mentionné que la ==
comparaison Integer
est une comparaison d'identité, ce qui n'est généralement pas ce que veut un programmeur, et que le but est de faire une comparaison de valeurs; Pourtant, j'ai fait un peu de science sur la façon de faire cette comparaison plus efficacement, à la fois en termes de compacité, d'exactitude et de vitesse du code.
J'ai utilisé le tas de méthodes habituelles:
public boolean method1() {
Integer i1 = 7, i2 = 5;
return i1.equals( i2 );
}
public boolean method2() {
Integer i1 = 7, i2 = 5;
return i1.intValue() == i2.intValue();
}
public boolean method3() {
Integer i1 = 7, i2 = 5;
return i1.intValue() == i2;
}
public boolean method4() {
Integer i1 = 7, i2 = 5;
return i1 == +i2;
}
public boolean method5() { // obviously not what we want..
Integer i1 = 7, i2 = 5;
return i1 == i2;
}
et a obtenu ce code après compilation et décompilation:
public boolean method1() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
return var1.equals( var2 );
}
public boolean method2() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method3() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method4() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method5() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2 == var1 ) {
return true;
} else {
return false;
}
}
Comme vous pouvez facilement le voir, la méthode 1 appelle Integer.equals()
(évidemment), les méthodes 2 à 4 donnent exactement le même code , déballant les valeurs au moyen de .intValue()
puis les comparant directement, et la méthode 5 déclenche simplement une comparaison d'identité, ce qui est la façon incorrecte de comparer les valeurs.
Étant donné que (comme déjà mentionné par exemple par JS) equals()
entraîne un surcoût (il doit le faire instanceof
et un cast non contrôlé), les méthodes 2-4 fonctionneront exactement à la même vitesse, remarquablement mieux que la méthode 1 lorsqu'elle est utilisée dans des boucles serrées, car HotSpot n'est pas susceptibles d'optimiser les moulages & instanceof
.
C'est assez similaire avec d'autres opérateurs de comparaison (par exemple <
/ >
) - ils déclencheront le déballage, tout en compareTo()
n'utilisant pas - mais cette fois, l'opération est hautement optimisable par HS car il ne intValue()
s'agit que d'une méthode getter (candidat idéal pour être optimisé).
À mon avis, la version 4 rarement utilisée est le moyen le plus concis - chaque développeur C / Java chevronné sait que unary plus est dans la plupart des cas égal à cast en int
/ .intValue()
- alors que cela peut être un petit moment WTF pour certains (principalement ceux qui ne l'ont pas fait) n'utilisez pas unary plus au cours de leur vie), cela montre sans doute l'intention de la manière la plus claire et la plus laconique - cela montre que nous voulons une int
valeur de l'un des opérandes, forçant ainsi l'autre valeur à être également déballée. Il est également incontestablement le plus similaire à la i1 == i2
comparaison régulière utilisée pour les int
valeurs primitives .
Mon vote va pour i1 == +i2
& i1 > i2
style pour les Integer
objets, à la fois pour des raisons de performances et de cohérence. Il rend également le code portable pour les primitives sans rien changer d'autre que la déclaration de type. Utiliser des méthodes nommées me semble introduire du bruit sémantique, semblable au bigInt.add(10).multiply(-3)
style très critiqué .