Je sais que si vous comparez un entier primitif encadré avec une constante telle que:
Integer a = 4;
if (a < 5)
a
sera automatiquement déballé et la comparaison fonctionnera.
Cependant, que se passe-t-il lorsque vous comparez deux encadrés Integers
et souhaitez comparer l'égalité ou moins que / supérieur à?
Integer a = 4;
Integer b = 5;
if (a == b)
Le code ci-dessus entraînera-t-il une vérification pour voir s'il s'agit du même objet, ou sera-t-il automatiquement décompressé dans ce cas?
Qu'en est-il de:
Integer a = 4;
Integer b = 5;
if (a < b)
?
java
integer
autoboxing
shmosel
la source
la source
==
au lieu deequals
donne le résultat correct, cela peut être dû au fait que les nombres encadrés sont internés ou autrement réutilisés (comme optimisation du compilateur, probablement). La raison de poser cette question est de savoir ce qui se passe en interne, pas ce qui semble se produire. (Réponses:
Non, == entre Entier, Long, etc. vérifiera l' égalité de référence - c'est-à-dire
cela vérifiera si
x
et faity
référence au même objet plutôt qu'aux objets égaux .Alors
est garanti pour imprimer
false
. L'internement de "petites" valeurs de zone automatique peut conduire à des résultats délicats:Cela s'imprimera
true
, en raison des règles de boxe ( section JLS 5.1.7 ). C'est toujours l'égalité de référence qui est utilisée, mais les références sont vraiment égales.Personnellement, j'utiliserais:
ou
Comme vous le dites, pour toute comparaison entre un type d'encapsuleur (
Integer
,Long
etc.) et un type numérique (int
,long
etc.), la valeur du type d'encapsuleur n'est pas mise en boîte et le test est appliqué aux valeurs primitives impliquées.Cela se produit dans le cadre de la promotion numérique binaire ( JLS section 5.6.2 ). Regardez la documentation de chaque opérateur pour voir si elle est appliquée. Par exemple, à partir des documents pour
==
et!=
( JLS 15.21.1 ):et pour
<
,<=
,>
et>=
( JLS 15.20.1 )Notez que rien de tout cela n'est considéré comme faisant partie de la situation où aucun type n'est un type numérique.
la source
x.compareTo(y) < 0
place dex < y
?==
testera toujours l'égalité des objets. Il est facile d'être dupe cependant:Vos exemples avec des inégalités fonctionneront car ils ne sont pas définis sur les objets. Cependant, avec la
==
comparaison, l'égalité des objets sera toujours vérifiée. Dans ce cas, lorsque vous initialisez les objets à partir d'une primitive encadrée, le même objet est utilisé (pour a et b). Il s'agit d'une optimisation correcte car les classes de boîtes primitives sont immuables.la source
200
, les deux tests s'imprimentfalse
.equals
être appelé».Depuis Java 1.7, vous pouvez utiliser Objects.equals :
la source
==
vérifie l'égalité de référence, cependant lors de l'écriture de code comme:Java est assez intelligent pour réutiliser la même immuable pour
a
etb
, cela est si vrai:a == b
. Curieux, j'ai écrit un petit exemple pour montrer où java cesse d'optimiser de cette façon:Lorsque je compile et exécute ceci (sur ma machine), j'obtiens:
la source
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
==
comparaisonInteger
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:
et a obtenu ce code après compilation et décompilation:
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 faireinstanceof
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 encompareTo()
n'utilisant pas - mais cette fois, l'opération est hautement optimisable par HS car il neintValue()
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 uneint
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 à lai1 == i2
comparaison régulière utilisée pour lesint
valeurs primitives .Mon vote va pour
i1 == +i2
&i1 > i2
style pour lesInteger
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 aubigInt.add(10).multiply(-3)
style très critiqué .la source
unary +
(unaire plus), voir par exemple stackoverflow.com/questions/2624410/…Appel
Fonctionnera la plupart du temps, mais il n'est pas garanti de toujours fonctionner, alors ne l'utilisez pas.
La façon la plus appropriée de comparer deux classes entières pour l'égalité, en supposant qu'elles soient nommées «a» et «b» est d'appeler:
Vous pouvez également utiliser cette méthode qui est légèrement plus rapide.
Sur ma machine, 99 milliards d'opérations ont pris 47 secondes en utilisant la première méthode et 46 secondes en utilisant la deuxième méthode. Vous auriez besoin de comparer des milliards de valeurs pour voir toute différence.
Notez que «a» peut être nul puisqu'il s'agit d'un objet. La comparaison de cette manière ne provoquera pas d'exception de pointeur nul.
Pour comparer plus et moins que, utilisez
la source
if (a==b)
ne fonctionne que pour les petites valeurs et ne fonctionnera pas la plupart du temps.Nous devrions toujours opter pour la méthode equals () pour comparer deux entiers, c'est la pratique recommandée.
Si nous comparons deux entiers en utilisant ==, cela fonctionnerait pour une certaine plage de valeurs entières (nombre entier de -128 à 127) en raison de l'optimisation interne de la JVM.
Veuillez voir des exemples:
Cas 1:
Dans le cas ci-dessus, la JVM utilise la valeur de a et b du pool mis en cache et renvoie la même instance d'objet (donc l'adresse de mémoire) de l'objet entier et nous obtenons les deux sont égaux. C'est une optimisation que la JVM fait pour certaines valeurs de plage.
Cas 2: Dans ce cas, a et b ne sont pas égaux car il ne vient pas avec la plage de -128 à 127.
Bonne façon:
J'espère que ça aide.
la source
Dans mon cas, j'ai dû comparer deux
Integer
s pour l'égalité où les deux pourraient êtrenull
. Recherche sur un sujet similaire, n'a rien trouvé d'élégant pour cela. Entré avec un utilitaire simple fonctions.la source
Parce que la méthode de comparaison doit être basée sur le type int (x == y) ou la classe Integer (x.equals (y)) avec l'opérateur droit
la source
cette méthode compare deux entiers avec une vérification nulle, voir les tests
la source
Objects.equals(x,y)
méthode au lieu de rouler la vôtre.