web-dev-qa-db-fra.com

Comment comparer deux entiers?

Je dois comparer deux Integer objets (pas int). Quelle est la manière canonique de les comparer?

Integer x = ...
Integer y = ...

Je peux penser à ceci:

if (x == y) 

Le == L'opérateur compare uniquement les références, donc cela ne fonctionnera que pour les valeurs entières inférieures. Mais peut-être que la boxe automatique intervient ...?

if (x.equals(y)) 

Cela ressemble à une opération coûteuse. Y a-t-il des codes de hachage calculés de cette façon?

if (x.intValue() == y.intValue())

Un peu bavard ...

EDIT: Merci pour vos réponses. Bien que je sache quoi faire maintenant, les faits sont répartis sur toutes les réponses existantes (même celles supprimées :)) et je ne sais pas vraiment laquelle accepter. J'accepterai donc la meilleure réponse, qui fait référence aux trois possibilités de comparaison, ou au moins aux deux premières.

34
Daniel Rikowski

Voici ce que fait la méthode des égaux:

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

Comme vous pouvez le voir, il n'y a pas de calcul de code de hachage, mais il y a quelques autres opérations qui s'y déroulent. Bien que x.intValue() == y.intValue() puisse être légèrement plus rapide, vous vous y trouvez en territoire de micro-optimisation. De plus, le compilateur peut de toute façon optimiser l'appel equals(), bien que je ne le sois pas certain.

J'utiliserais généralement la primitive int, mais si je devais utiliser Integer, je resterais avec equals().

33
Jeff

Utilisez la méthode equals. Pourquoi êtes-vous si inquiet que cela coûte cher?

26
svenningsson
if (x.equals(y))

Cela ressemble à une opération coûteuse. Y a-t-il des codes de hachage calculés de cette façon?

Ce n'est pas une opération coûteuse et aucun code de hachage n'est calculé. Java ne calcule pas comme par magie les codes de hachage, equals(...) est juste un appel de méthode, pas différent de tout autre appel de méthode.

La JVM optimisera probablement même l'appel de méthode (en soulignant la comparaison qui a lieu à l'intérieur de la méthode), donc cet appel n'est pas beaucoup plus cher que d'utiliser == Sur deux valeurs primitives int.

Remarque: N'appliquez pas de micro-optimisations prématurément; vos hypothèses comme "cela doit être lent" sont très probablement erronées ou n'ont pas d'importance, car le code n'est pas un goulot d'étranglement des performances.

13
Jesper

Note mineure: depuis Java 1.7 la classe Integer a une méthode statique compare(Integer, Integer), donc vous pouvez simplement appeler Integer.compare(x, y) et en finir avec elle (questions sur optimisation de côté).

Bien sûr, ce code est incompatible avec les versions de Java avant 1.7, donc je recommanderais d'utiliser x.compareTo(y) à la place, qui est compatible avec 1.2.

9
ktbiz

J'irais avec x.equals (y) parce que c'est un moyen cohérent de vérifier l'égalité pour toutes les classes.

En ce qui concerne les performances, égal est en fait plus cher car il finit par appeler intValue ().

EDIT: Vous devez éviter la boîte automatique dans la plupart des cas. Cela peut devenir vraiment déroutant, en particulier l'auteur ne sait pas ce qu'il faisait. Vous pouvez essayer ce code et vous serez surpris par le résultat;

Integer a = 128;
Integer b = 128;

System.out.println(a==b);
8
ZZ Coder

"est égal" est-ce. Pour être sûr, vous devez tester la nullité:

x == y || (x != null && x.equals(y))

les tests x == y pour null == null, ce qui à mon humble avis devrait être vrai.

Le code sera inséré par le JIT s'il est appelé assez souvent, donc les considérations de performances ne devraient pas avoir d'importance.

Bien sûr, éviter le "Entier" au profit de "int" est le meilleur moyen, si vous le pouvez.

[Ajoutée]

De plus, le contrôle nul est nécessaire pour garantir que le test d'égalité est symétrique - x.equals (y) devrait être identique à y.equals (x), mais ne l'est pas si l'un d'eux est nul.

2
mfx

Comparez l'entier et imprimez sa valeur dans l'ordre croissant ou décroissant. Tout ce que vous avez à faire est d'implémenter l'interface du comparateur et de remplacer sa méthode de comparaison et de comparer sa valeur comme ci-dessous:

@Override
public int compare(Integer o1, Integer o2) {
    if (ascending) {
        return o1.intValue() - o2.intValue();
    } else {
        return o2.intValue() - o1.intValue();
    }

}
2
user3468976

Je viens de rencontrer cela dans mon code et il m'a fallu un certain temps pour le comprendre. Je faisais une intersection de deux listes triées et n'obtenais que de petits nombres dans ma sortie. Je pourrais le faire fonctionner en utilisant (x - y == 0) au lieu de (x == y) pendant la comparaison.

1
Abhinav

La classe Integer implémente Comparable<Integer>, Vous pouvez donc essayer,

x.compareTo(y) == 0

aussi, si plutôt que l'égalité, vous cherchez à comparer ces entiers, alors,

x.compareTo(y) < 0 vous dira si x est inférieur à y.

x.compareTo(y) > 0 vous dira si x est supérieur à y.

Bien sûr, il serait sage, dans ces exemples, de s'assurer que x n'est pas nul avant d'effectuer ces appels.

1
jhumble