web-dev-qa-db-fra.com

Java: String: equalsIgnoreCase vs tout basculer en majuscules / minuscules

Il est venu à mon attention qu'il existe plusieurs façons de comparer les chaînes en Java.

Je viens de prendre l'habitude il y a longtemps d'utiliser equalsIgnoreCase pour éviter d'avoir des problèmes avec les chaînes sensibles à la casse.

D'autres, par contre, préfèrent tout passer en majuscules ou en minuscules.

D'où je me tiens (même si techniquement je suis assis), je ne vois pas de réelle différence.

Est-ce que quelqu'un sait si une pratique est meilleure que l'autre? Et si oui pourquoi?

25
Jason Rogers

Utilisez equalsIgnoreCase car il est plus lisible que de convertir les deux chaînes en majuscules avant une comparaison. La lisibilité l'emporte sur la micro-optimisation.

Quoi de plus lisible?

if (myString.toUpperCase().equals(myOtherString.toUpperCase())) {

ou

if (myString.equalsIgnoreCase(myOtherString)) {

Je pense que nous pouvons tous convenir que equalsIgnoreCase est plus lisible.

50
Asaph

equalsIgnoreCase évite les problèmes concernant les différences spécifiques aux paramètres régionaux (par exemple, dans les paramètres régionaux turcs, il existe deux lettres "i" majuscules différentes). En revanche, Maps utilise uniquement la méthode equals ().

10
koljaTM

Mais le problème dans ce dernier, où vous faites un hypothèse que les majuscules ou les minuscules sont passées, vous ne pouvez pas faire confiance aveuglément à l'appelant. Vous devez donc inclure une instruction ASSERT au début de la méthode pour vous assurer que l'entrée est toujours dans le cas auquel vous vous attendez.

3
rkg

Ni l'un ni l'autre n'est meilleur, ils ont tous deux leurs utilisations dans différents scénarios.

Souvent, lorsque vous devez faire des comparaisons de chaînes, il est possible de masser au moins l'une des chaînes pour faciliter la comparaison, et dans ces cas, vous verrez des chaînes converties en un cas particulier, coupées, etc. avant d'être comparées.

Si, d'un autre côté, vous voulez simplement faire une comparaison à la volée insensible à la casse de deux chaînes, n'hésitez pas à utiliser equalsIgnoreCase, c'est pour cela que c'est là pour tout. Je voudrais toutefois vous avertir que si vous voyez beaucoup de equalsIgnoreCase cela pourrait être une odeur de code.

2
CurtainDog

Cela dépend du cas d'utilisation.

Si vous effectuez une comparaison de chaîne une à une, equalsIgnoreCase est probablement plus rapide, car en interne, il ne fait que mettre en majuscule chaque caractère lors de son itération dans les chaînes (le code ci-dessous provient de Java.lang.String), ce qui est légèrement plus rapide que la mise en majuscule ou la minuscule. tous avant d'effectuer la même comparaison:

if (ignoreCase) 
{
    // If characters don't match but case may be ignored,
    // try converting both characters to uppercase.
    // If the results match, then the comparison scan should
    // continue.
    char u1 = Character.toUpperCase(c1);
    char u2 = Character.toUpperCase(c2);
    if (u1 == u2) {
        continue;
    }
    // Unfortunately, conversion to uppercase does not work properly
    // for the Georgian alphabet, which has strange rules about case
    // conversion.  So we need to make one last check before
    // exiting.
    if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
        continue;
    }
}

Mais lorsque vous avez une situation où vous souhaitez effectuer des recherches par rapport à une structure de données remplie de chaînes (en particulier les chaînes qui se trouvent toutes dans l'espace US Latin/ASCII) de manière insensible à la casse, il sera plus rapide de couper/minuscule les chaînes pour être comparé et les mettre dans quelque chose comme un HashSet ou HashMap.

C'est mieux que d'appeler equalsIgnoreCase sur chaque élément d'une liste car le léger gain de performances de equalsIgnoreCase () est annulé par le fait que vous faites essentiellement une version modifiée de contains () contre un tableau, qui est O (n) . Avec une chaîne pré-normalisée, vous pouvez vérifier la liste complète des chaînes avec un seul appel contains () qui s'exécute dans O (1).

1
Jim W

documentation equalsIgnoreCase dans jdk 8

  • Compare cette chaîne à une autre chaîne, en ignorant les considérations de casse. Deux chaînes sont considérées comme respectant la casse si elles sont de la même longueur et les caractères correspondants dans les deux chaînes sont égales si la casse est ignorée.

    Deux caractères c1 et c2 sont considérés comme la même casse ignorante si au moins une des conditions suivantes est vraie:

    • Les deux caractères sont identiques (comparés par l'opérateur ==)
    • L'application de la méthode Java.lang.CharactertoUpperCase (char) à chaque caractère produit le même résultat
    • L'application de la méthode Java.lang.CharactertoLowerCase (char) à chaque caractère produit le même résultat

Mes pensées:

Donc, en utilisant equalsIgnoreCase, nous parcourons les chaînes (uniquement si leurs valeurs de taille sont les mêmes) en comparant chaque caractère. Dans le pire des cas, les performances seront O (3cn) où n = la taille de vos chaînes. Nous n'utiliserons aucun espace supplémentaire.

En utilisant toUpper () puis en comparant si les chaînes sont égales, vous bouclez TOUJOURS chaque chaîne une fois, convertissant toutes les chaînes en supérieur, puis faites une équivalence par vérification de référence (equals ()). C'est thêta (2n + c). Mais rappelez-vous juste que lorsque vous faites toUpperCase (), vous devez en fait créer deux nouvelles chaînes car les chaînes en Java sont immuables.

Je dirais donc qu'equalsIgnoreCase est à la fois plus efficace et plus facile à lire.

Encore une fois, je considérerais le cas d'utilisation, car ce serait le problème pour moi. L'approche toUpper pourrait être valide dans certains cas d'utilisation, mais 98% du temps j'utilise equalsIgnoreCase ().

1
andrew dibiasio

Les performances sont les mêmes selon cet article:

http://www.params.me/2011/03/stringtolowercasestringtouppercase-vs.html

Je déciderais donc en fonction de la lisibilité du code, dans certains cas, toLowerCase () serait mieux si je transmettais toujours une valeur à une seule méthode pour créer des objets, sinon equalsIgnoreCase () est plus logique.

1
Sileria

Lorsque je travaille avec des caractères en anglais uniquement, j'exécute toujours toUpperCase() ou toLowerCase() avant de commencer à faire des comparaisons si j'appelle .equalsIgnoreCase()plusieurs fois ou si j'utilise une instruction switch. De cette façon, il effectue l'opération de changement de casse une seule fois et est donc plus efficace.

Par exemple, dans un modèle d'usine:

public static SuperObject objectFactory(String objectName) {
    switch(objectName.toUpperCase()) {
        case "OBJECT1":
            return new SubObject1();
            break;
        case "OBJECT2":
            return new SubObject2();
            break;
        case "OBJECT3":
            return new SubObject3();
            break;
    }
    return null;
}

(L'utilisation d'une instruction switch est légèrement plus rapide que if..else if..else blocs pour la comparaison des chaînes)

0
4castle