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;?


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


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.


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


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.


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 ().


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;


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.


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.