Soll ich string.isEmpty () oder "" .equals (string) verwenden?

171

Der Titel sagt im Grunde alles. Normalerweise teste ich dies zusammen mit a string == null, daher mache ich mir keine Sorgen um einen null-sicheren Test. Welches soll ich verwenden?

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

oder

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

In diesem Sinne - macht isEmpty()überhaupt etwas anderes als return this.equals("");oder return this.length() == 0;?

Matt Ball
quelle
26
Beachten Sie, dass dies isEmpty()nur Java 6+ ist.
ColinD
1
Sie können eine Hilfsmethode Util.String.hasValue (String s) erstellen, die nach Null, Leere und Leerzeichen sucht, um alle Fälle zu behandeln.
Cloudanger
5
@ColinD Wahrscheinlich kein Problem - J2SE 5.0 hat vor einiger Zeit seine Lebensdauer beendet.
Tom Hawtin - Tackline
1
Eine andere zu berücksichtigende Sache ist, dass "" .equals () Object als Argument verwendet, sodass Sie keinen Compilerfehler erhalten, wenn der Argumenttyp von String zu etwas anderem wechselt, zum Guten oder Schlechten.
Paul Jackson

Antworten:

251

Der Hauptvorteil von "".equals(s)ist, dass Sie die Nullprüfung nicht benötigen ( equalsüberprüft ihr Argument und gibt zurück, falsewenn sie null ist), was Sie anscheinend nicht interessiert. Wenn Sie sich keine Sorgen darüber machen s, null zu sein (oder auf andere Weise danach suchen), würde ich dies definitiv verwenden s.isEmpty(). Es zeigt genau, was Sie überprüfen. Es ist Ihnen swichtig, ob es leer ist oder nicht , und nicht, ob es der leeren Zeichenfolge entspricht

Michael Mrozek
quelle
29
Vielen Dank für die Erklärung. Jetzt weiß ich, warum ich "" .equals (str) gegenüber str.equals ("") bevorzugen soll! Ich habe mich immer gefragt, warum andere dies so oft verwenden, aber Nullwerte nicht berücksichtigt. Großartig :-)
Peter Wippermann
10
IMHO wird die Nullprüfung in den obigen Beispielen weiterhin benötigt, da wir davon ausgehen, dass die Bedingung für den Nullwert wahr sein sollte. s == null || "" .equals (s)
mkorpela
5
@ Master.Aurora nein, wenn getValue()null zurückgegeben, würden Sie eine NullPointerException erhalten, wenn toString()aufgerufen wurde
ataulm
12
@RenniePet Es ist nicht so, als wäre Magie involviert. Wenn snull ist, können Sie keine Methoden dafür aufrufen - es ist null. ""wird niemals null sein, also können Sie Methoden sicher aufrufen und equals()den Fall behandeln, in dem sein Argument null ist
Michael Mrozek
5
Ein Hinweis zur Leistung: isEmpty()Überprüft die interne Länge eines privaten Arrays, während equals(Object anObject)viel mehr (z instanceof. B. Überprüfung ). In Bezug auf die Leistung isEmpty()ist in der Regel schneller.
Turing85
82

String.equals("")ist eigentlich etwas langsamer als nur ein isEmpty()Anruf. Strings speichern eine im Konstruktor initialisierte Zählvariable, da Strings unveränderlich sind.

isEmpty() vergleicht die Zählvariable mit 0, während equals den Typ und die Zeichenfolgenlänge überprüft und dann zum Vergleich über die Zeichenfolge iteriert, wenn die Größen übereinstimmen.

Also, um Ihre Frage zu beantworten, isEmpty()wird tatsächlich viel weniger tun! und das ist gut so.

David Young
quelle
3
Ich denke in diesem Fall trifft der Unterschied nicht zu; Es wird niemals eine Iteration über die Zeichenfolgen zum Vergleich geben, da die Größen nicht übereinstimmen (es sei denn, die Zeichenfolge ist tatsächlich leer und es gibt keine Zeichen, über die iteriert werden kann)
Michael Mrozek
2
Richtig, aber bei Gleichheit wird zuerst eine Referenzprüfung durchgeführt, um festzustellen, ob es sich um dasselbe Objekt handelt, dann eine Instanz von, dann eine Umwandlung in einen String, eine Längenprüfung und schließlich die Iteration. Wenn beide Strings leer wären, wäre dies jedoch nur eine einfache Referenzprüfung.
David Young
Quellcode für die String-Klasse ist verfügbar java2s.com/Open-Source/Java-Document/6.0-JDK-Core/lang/java/…
David Young
1
@ David toter Link; Hier ist ein Live- Dokument docjar.com/html/api/java/lang/String.java.html#1011
Matt Ball
17

Eine Sache, die Sie neben den anderen genannten Problemen berücksichtigen sollten, ist die isEmpty()in 1.6 eingeführte. Wenn Sie sie also verwenden, können Sie den Code nicht unter Java 1.5 oder niedriger ausführen.

Fabian Steeg
quelle
4
Das ist definitiv kein Problem für mich.
Matt Ball
1
Auch diese Antwort ist jetzt vor 6 Jahren. Ich würde hoffen, dass niemand mehr etwas Altes wie Java 1.5 verwenden muss.
Mischa Nasledov
1
Es gibt in der Tat viele Dinge, die beim Upgrade einer Java-Version kaputt gehen können. Dies ist für eine Back-End-Anwendung, die auf einem großen Server ausgeführt wird, weniger kritisch, für Clientanwendungen jedoch von Bedeutung. Die grafischen Bibliotheken und Garbage Collection-Strategien werden häufig von größeren und kleineren Java-Upgrades beeinflusst. Darüber hinaus kann Client-Software auf verschiedenen Betriebssystemen und manchmal mit begrenztem Speicher ausgeführt werden, was bedeutet, dass Sie häufig nicht über das Budget / die Ressourcen verfügen, um alles zu testen. - Ja, ich habe Kunden, die 2017 immer noch bei Java 5 bleiben.
bvdb
15

Sie können Apache Commons verwenden. StringUtils isEmpty () oder isNotEmpty ().

Kühle Bohnen
quelle
1
@ 2019 und wir brauchen noch eine Bibliothek von Drittanbietern dafür: seufz:
Adam
2

Es ist nicht wirklich wichtig. "".equals(str)ist meiner Meinung nach klarer.

isEmpty()kehrt zurück count == 0;

Kylar
quelle
47
Ich würde sagen, str.isEmpty()ist viel klarer als "".equals(str). Es liest sich als das, was Sie überprüfen. Meinungsfrage, denke ich.
ColinD
7
Ich denke, einige Leute bevorzugen "" .equals (str), um NPE zu vermeiden. Ich persönlich mag es nicht, weil ich lieber zuerst prüfen möchte, ob der String nicht null ist.
CoolBeans
2

Ich habe eine Testerklasse geschrieben, die die Leistung testen kann:

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));
    }
}

Ich fand, dass die Verwendung von .isEmpty () ungefähr die Hälfte der Zeit von .equals ("") dauerte.

conapart3
quelle
Dies ist kein gültiges Mikrobenchmark. Ich würde dringend empfehlen, Caliper oder ein ähnliches speziell entwickeltes Benchmarking-Tool zu verwenden. stackoverflow.com/q/504103/139010
Matt Ball
Danke für den Tipp! Wenn ich etwas Freizeit habe, werde ich mit Mikro-Benchmarking experimentieren und meine Antwort aktualisieren.
Conapart3