web-dev-qa-db-fra.com

Compare deux objets en Java avec des valeurs null possibles

Je souhaite comparer deux chaînes pour l'égalité en Java, lorsque l'un ou les deux pourraient être null, je ne peux donc pas simplement appeler .equals(). Quel est le meilleur moyen?

boolean compare(String str1, String str2) {
    ...
}

Modifier: 

return ((str1 == str2) || (str1 != null && str1.equals(str2)));
128
priceline

C'est ce que le code interne de Java utilise (sur d'autres méthodes compare):

public static boolean compare(String str1, String str2) {
    return (str1 == null ? str2 == null : str1.equals(str2));
}
144
Eric

Depuis Java 7, vous pouvez utiliser la méthode statique Objects.equals(Object, Object) pour effectuer des vérifications égales sur deux objets sans vous soucier de la valeur null.

Si les deux objets sont null, il retournera true, si l'un est null et l'autre non, il retournera false. Sinon, le résultat de l'appel equals sera renvoyé sur le premier objet avec le second comme argument.

195
Mark Rotteveel

Pour ces cas, il serait préférable d'utiliser Apache CommonsStringUtils # est égal à , il gère déjà les chaînes vides. Exemple de code:

public boolean compare(String s1, String s2) {
    return StringUtils.equals(s1, s2);
}

Si vous ne voulez pas ajouter la bibliothèque, copiez simplement le code source de la méthode StringUtils#equals et appliquez-le quand vous en avez besoin.

37
Luiggi Mendoza

Pour ceux sur Android, qui ne peuvent pas utiliser Objects.equals (str1, str2) de l'API 19, voici ce qui suit:

Android.text.TextUtils.equals(str1, str2);

C'est nul en sécurité. La méthode string.equals (), plus coûteuse, est rarement utilisée car les chaînes identiques sous Android se comparent presque toujours vrai avec l'opérande "==" grâce à Le pooling de chaînes d'Android , et les vérifications de longueur sont un moyen rapide de filtrer la plupart des inadéquations.

Code source:

/**
 * Returns true if a and b are equal, including if they are both null.
 * <p><i>Note: In platform versions 1.1 and earlier, this method only worked  well if
 * both the arguments were instances of String.</i></p>
 * @param a first CharSequence to check
 * @param b second CharSequence to check
 * @return true if a and b are equal
 */
public static boolean equals(CharSequence a, CharSequence b) {
    if (a == b) return true;
    int length;
    if (a != null && b != null && (length = a.length()) == b.length()) {
        if (a instanceof String && b instanceof String) {
            return a.equals(b);
        } else {
            for (int i = 0; i < length; i++) {
                if (a.charAt(i) != b.charAt(i)) return false;
            }
            return true;
        }
    }
    return false;
}
25
NameSpace

Depuis la version 3.5, Apache Commons StringUtils utilise les méthodes suivantes:

static int  compare(String str1, String str2)
static int  compare(String str1, String str2, boolean nullIsLess)
static int  compareIgnoreCase(String str1, String str2)
static int  compareIgnoreCase(String str1, String str2, boolean nullIsLess)

Celles-ci fournissent une comparaison de chaîne null safe.

6
phn

Comparez deux chaînes en utilisant la méthode equals (-, -) et equalsIgnoreCase (-, -) de la classe Apache Commons StringUtils.

StringUtils.equals (-, -) :

StringUtils.equals(null, null)   = true
StringUtils.equals(null, "abc")  = false
StringUtils.equals("abc", null)  = false
StringUtils.equals("abc", "abc") = true
StringUtils.equals("abc", "ABC") = false

StringUtils.equalsIgnoreCase (-, -) :

StringUtils.equalsIgnoreCase(null, null)   = true
StringUtils.equalsIgnoreCase(null, "abc")  = false
StringUtils.equalsIgnoreCase("xyz", null)  = false
StringUtils.equalsIgnoreCase("xyz", "xyz") = true
StringUtils.equalsIgnoreCase("xyz", "XYZ") = true
3
Prashant Sahoo
boolean compare(String str1, String str2) {
    if(str1==null || str2==null) {
        //return false; if you assume null not equal to null
        return str1==str2;
    }
    return str1.equals(str2);
}

est-ce ce que vous avez désiré?

2
didxga

Vous pouvez utiliser Java.util.Objects comme suit.

public static boolean compare(String str1, String str2) {
    return Objects.equals(str1, str2);
}
1
Jobi Subramunian
boolean compare(String str1, String str2) {
    if (str1 == null || str2 == null)
        return str1 == str2;

    return str1.equals(str2);
}
1
Kierrow
boolean compare(String str1, String str2) {
  return (str1==null || str2==null) ? str1 == str2 : str1.equals(str2);
}
1
Sumit Singh

OK, alors que signifie "meilleure solution possible"?

Si vous voulez dire plus lisible, toutes les solutions possibles sont à peu près équivalentes pour un programmeur expérimenté Java. Mais l’OMI le plus lisible est-ce

 public boolean compareStringsOrNulls(String str1, String str2) {
     // Implement it how you like
 }

En d'autres termes, masquez l'implémentation dans une méthode simple qui (idéalement) peut être en ligne.

(Vous pouvez également "externaliser" une bibliothèque d'utilitaires tiers ... si vous l'utilisez déjà dans votre base de code.)


Si vous voulez dire le plus performant, alors:

  1. la solution la plus performante dépend de la plate-forme et du contexte,
  2. un des problèmes de "contexte" est la fréquence relative (dynamique) d'apparition de null arguments,
  3. il probablement peu importe la version la plus rapide ... car la différence est probablement trop petite pour avoir une incidence sur les performances globales de l'application, et
  4. si cela compte, le seul moyen de déterminer lequel est le plus rapide sur votre plate-forme est d'essayer les deux versions et de mesurer la différence.
0
Stephen C

Utilisation de Java 8:

private static Comparator<String> nullSafeStringComparator = Comparator
        .nullsFirst(String::compareToIgnoreCase); 

private static Comparator<Metadata> metadataComparator = Comparator
        .comparing(Metadata::getName, nullSafeStringComparator)
        .thenComparing(Metadata::getValue, nullSafeStringComparator);

public int compareTo(Metadata that) {
    return metadataComparator.compare(this, that);
}
0
TanvirChowdhury