Dois-je utiliser string.isEmpty () ou «» .equals (string)?

171

Le titre dit tout. Je teste généralement cela avec un string == null, donc je ne suis pas vraiment préoccupé par un test de sécurité nulle. Lequel dois-je utiliser?

String s = /* whatever */;
...
if (s == null || "".equals(s))
{
    // handle some edge case here
}

ou

if (s == null || s.isEmpty())
{
    // handle some edge case here
}

Sur cette note - fait isEmpty()même autre chose que return this.equals("");ou return this.length() == 0;?

Matt Ball
la source
26
Gardez à l'esprit qu'il isEmpty()s'agit uniquement de Java 6+.
ColinD le
1
Vous pouvez créer une méthode d'assistance Util.String.hasValue (String s) qui vérifie la valeur NULL, la vacuité et les espaces pour gérer tous les cas.
Cloudanger
5
@ColinD Probablement pas un problème - J2SE 5.0 a terminé sa période de fin de vie il y a quelque temps.
Tom Hawtin - tackline
1
Une autre chose à considérer est "" .equals () prend Object comme argument, donc vous n'obtiendrez pas une erreur du compilateur si le type d'argument change de String à autre chose, pour le meilleur ou pour le pire.
Paul Jackson

Réponses:

251

Le principal avantage de "".equals(s)est que vous n'avez pas besoin de la vérification de null ( equalsvérifiera son argument et retournera falses'il est nul), ce dont vous semblez ne pas vous soucier. Si vous n'êtes pas inquiet d' sêtre nul (ou si vous le vérifiez autrement), j'utiliserais certainement s.isEmpty(); il montre exactement ce que vous vérifiez, vous vous souciez de savoir si sc'est vide ou non , pas si cela équivaut à la chaîne vide

Michael Mrozek
la source
29
Merci pour l'explication. Maintenant je sais pourquoi favoriser "" .equals (str) sur str.equals ("")! Je me demandais toujours pourquoi les autres l'utilisaient si souvent, mais je ne tenais pas compte des valeurs nulles. Super :-)
Peter Wippermann
10
À mon humble avis, la vérification null est toujours nécessaire dans les exemples ci-dessus car nous supposons que la condition doit être vraie pour une valeur nulle. s == null || "" .equals (s)
mkorpela
5
@ Master.Aurora non, si getValue()retourné null, vous obtiendrez une NullPointerException lors de l' toString()appel
ataulm
12
@RenniePet Ce n'est pas comme s'il y avait de la magie. Si sest null, vous ne pouvez pas appeler de méthodes dessus - il est nul. ""ne sera jamais nul, vous pouvez donc appeler des méthodes dessus en toute sécurité et equals()pouvez gérer le cas où son argument est nul
Michael Mrozek
5
Une note sur les performances: isEmpty()vérifie la longueur interne d'un tableau privé alors que equals(Object anObject)fait beaucoup plus (par exemple, vérification instanceof). En termes de performances, isEmpty()est généralement plus rapide.
Turing85
82

String.equals("")est en fait un peu plus lent qu'un simple isEmpty()appel. Les chaînes stockent une variable de comptage initialisée dans le constructeur, car les chaînes sont immuables.

isEmpty() compare la variable count à 0, tandis que equals vérifie le type, la longueur de la chaîne, puis effectue une itération sur la chaîne à des fins de comparaison si les tailles correspondent.

Donc, pour répondre à votre question, vous isEmpty()en ferez beaucoup moins! et c'est une bonne chose.

David Young
la source
3
Je pense que dans ce cas, la différence ne s'applique pas; il n'y aura jamais d'itération sur les chaînes à des fins de comparaison, car les tailles ne correspondent pas (à moins que la chaîne ne soit réellement vide et qu'il n'y ait pas de caractères à parcourir)
Michael Mrozek
2
Vrai mais avec des égaux, vous devez d'abord vérifier les références pour voir s'il s'agit du même objet, puis une instanceof, puis une conversion en String, une vérification de la longueur, et enfin l'itération. Si les deux chaînes étaient vides, alors ce ne serait qu'une simple vérification de référence.
David Young
le code source de la classe String est disponible java2s.com/Open-Source/Java-Document/6.0-JDK-Core/lang/java/…
David Young
1
@David lien mort; voici un live docjar.com/html/api/java/lang/String.java.html#1011
Matt Ball
17

Une chose que vous voudrez peut - être envisager d' ailleurs les autres questions mentionnées est que isEmpty()a été introduit en 1.6, donc si vous l' utilisez, vous ne serez pas en mesure d'exécuter le code sur Java 1.5 ou ci - dessous.

Fabian Steeg
la source
4
Ce n'est certainement pas une préoccupation pour moi.
Matt Ball
1
De plus, cette réponse remonte à 6 ans. J'espère que personne n'a plus besoin d'utiliser quelque chose d'ancien comme Java 1.5.
Misha Nasledov le
1
Il y a en fait beaucoup de choses qui peuvent casser lors de la mise à jour d'une version java. C'est moins critique pour une application back-end qui s'exécute sur un gros serveur, mais c'est important pour les applications clientes. Les bibliothèques graphiques et les stratégies de garbage collection sont souvent affectées par les mises à niveau majeures et mineures de Java. En plus de cela, le logiciel client peut fonctionner sur différents systèmes d'exploitation et parfois avec une mémoire limitée, ce qui signifie que vous n'aurez souvent pas le budget / les ressources pour tout tester. - Oui, j'ai des clients qui s'en tiennent toujours à Java 5 en 2017.
bvdb
15

Vous pouvez utiliser apache commons StringUtils isEmpty () ou isNotEmpty ().

Fèves fraîches
la source
1
@ 2019 et nous avons encore besoin d'une bibliothèque tierce pour cela: soupir:
Adam le
2

Cela n'a pas vraiment d'importance. "".equals(str)est plus clair à mon avis.

isEmpty()retourne count == 0;

Kylar
la source
47
Je dirais que str.isEmpty()c'est beaucoup plus clair que "".equals(str). Il se lit comme ce que vous vérifiez. Question d'opinion cependant, je suppose.
ColinD le
7
Je pense que certaines personnes préfèrent faire "" .equals (str) pour éviter les NPE. Personnellement, je n'aime pas ça parce que je préfère vérifier que la chaîne n'est pas nulle en premier.
CoolBeans
2

J'ai écrit une classe de testeur qui peut tester les performances:

public class Tester
{
    public static void main(String[] args)
    {
        String text = "";

        int loopCount = 10000000;
        long startTime, endTime, duration1, duration2;

        startTime = System.nanoTime();
        for (int i = 0; i < loopCount; i++) {
            text.equals("");
        }
        endTime = System.nanoTime();
        duration1 = endTime - startTime;
        System.out.println(".equals(\"\") duration " +": \t" + duration1);

        startTime = System.nanoTime();
        for (int i = 0; i < loopCount; i++) {
            text.isEmpty();
        }
        endTime = System.nanoTime();
        duration2 = endTime - startTime;
        System.out.println(".isEmpty() duration "+": \t\t" + duration2);

        System.out.println("isEmpty() to equals(\"\") ratio: " + ((float)duration2 / (float)duration1));
    }
}

J'ai trouvé que l'utilisation de .isEmpty () prenait environ la moitié du temps de .equals ("").

conapart3
la source
Ce n'est pas un microbenchmark valide. Je recommanderais fortement d'utiliser Caliper ou un outil d'analyse comparative similaire. stackoverflow.com/q/504103/139010
Matt Ball
Merci pour le conseil! Quand j'aurai du temps libre, j'expérimenterai des micro-analyses comparatives et je mettrai à jour ma réponse.
conapart3