Powinienem użyć string.isEmpty () czy „” .equals (string)?


171

Tytuł w zasadzie mówi wszystko. Zwykle testuję to obok a string == null, więc nie martwię się testem zerowym. Którego powinienem użyć?

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

lub

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

W tej notatce - czy isEmpty()nawet robi coś innego niż return this.equals("");lub return this.length() == 0;?


26
Należy pamiętać, że isEmpty()jest to tylko Java 6+.
ColinD,

1
Możesz stworzyć pomocniczą metodę Util.String.hasValue (String s), która sprawdza null, pustkę i białe znaki, aby obsłużyć wszystkie przypadki.
Cloudanger,

5
@ColinD Prawdopodobnie to nie problem - J2SE 5.0 zakończył swój okres użytkowania jakiś czas temu.
Tom Hawtin - tackline

1
Inną rzeczą do rozważenia jest "" .equals () przyjmuje Object jako argument, więc nie otrzymasz błędu kompilatora, jeśli typ argumentu zmieni się z String na coś innego, na lepsze lub gorsze.
Paul Jackson,

Odpowiedzi:


251

Główną korzyścią "".equals(s)jest to, że nie potrzebujesz sprawdzania wartości null ( equalssprawdzi argument i zwróci, falsejeśli jest zerowy), co wydaje się nie obchodzić. Jeśli nie martwisz się, że masz swartość zerową (lub w inny sposób go sprawdzasz), zdecydowanie użyłbym s.isEmpty(); pokazuje dokładnie to, co sprawdzasz, obchodzi cię, czy sjest pusty, a nie, czy jest równy pustemu ciągowi


29
Dziękuję za wyjaśnienie. Teraz wiem, dlaczego faworyzować „” .equals (str) nad str.equals („”)! Zawsze się zastanawiałem, dlaczego inni używają tego tak często, ale nie brałem pod uwagę wartości zerowych. Świetnie :-)
Peter Wippermann

10
IMHO sprawdzenie wartości null jest nadal potrzebne w powyższych przykładach, ponieważ zakładamy, że warunek powinien być prawdziwy dla wartości null. s == null || „” .equals (s)
mkorpela,

5
@ Master.Aurora nie, jeśli getValue()zwrócona wartość null, otrzymasz wyjątek NullPointerException po toString()wywołaniu
ataulm

12
@RenniePet To nie jest jakaś magia. Jeśli sjest null, nie możesz wywołać metod na nim - jest null. ""nigdy nie będzie null, więc możesz bezpiecznie wywoływać na nim metody i equals()poradzić sobie z przypadkiem, w którym jego argument jest pusty
Michael Mrozek

5
Uwaga na temat wydajności: isEmpty()sprawdza wewnętrzną długość tablicy prywatnej, ale equals(Object anObject)robi znacznie więcej (np. Sprawdza instanceof). Pod względem wydajności isEmpty()jest generalnie szybszy.
Turing85,

82

String.equals("")jest w rzeczywistości nieco wolniejszy niż zwykłe isEmpty()połączenie. Ciągi przechowują zmienną count zainicjowaną w konstruktorze, ponieważ ciągi są niezmienne.

isEmpty() porównuje zmienną count z wartością 0, a equals sprawdzi typ, długość ciągu, a następnie iteruje po ciągu w celu porównania, jeśli rozmiary są zgodne.

Więc odpowiadając na twoje pytanie, isEmpty()zrobisz o wiele mniej! i to dobrze.


3
Myślę, że w tym przypadku różnica nie ma zastosowania; nigdy nie będzie iteracji po łańcuchach dla porównania, ponieważ rozmiary nie będą pasować (chyba że ciąg faktycznie jest pusty, a wtedy nie ma znaków do iteracji)
Michael Mrozek

2
To prawda, ale w przypadku równych wartości najpierw sprawdzasz referencję, aby zobaczyć, czy są to ten sam obiekt, potem instancja, potem rzutowanie na String, sprawdzenie długości, a na końcu iteracja. Gdyby oba ciągi były puste, byłoby to tylko proste sprawdzenie referencji.
David Young,


1
@David martwy link; oto jeden na żywo docjar.com/html/api/java/lang/String.java.html#1011
Matt Ball

17

Oprócz innych wymienionych kwestii warto rozważyć jedną rzecz, która isEmpty()została wprowadzona w wersji 1.6, więc jeśli jej użyjesz, nie będziesz w stanie uruchomić kodu w Javie 1.5 lub starszym.


4
To na pewno nie dotyczy mnie.
Matt Ball

1
Również ta odpowiedź jest teraz 6 lat temu. Mam nadzieję, że nikt nie musi już używać czegoś starożytnego, takiego jak Java 1.5.
Misha Nasledov

1
W rzeczywistości jest wiele rzeczy, które mogą się zepsuć podczas uaktualniania wersji Java. Jest to mniej krytyczne dla aplikacji zaplecza, które działa na dużym serwerze, ale ma znaczenie dla aplikacji klienckich. Na biblioteki graficzne i strategie wyrzucania elementów bezużytecznych często mają wpływ główne i drobne aktualizacje Java. Co więcej, oprogramowanie klienckie może działać w różnych systemach operacyjnych, a czasem z ograniczoną pamięcią, co oznacza, że ​​często nie masz budżetu / zasobów, aby wszystko przetestować. - Tak, mam klientów, którzy nadal trzymają się Java 5 w 2017 r.
bvdb

15

Możesz użyć apache commons StringUtils isEmpty () lub isNotEmpty ().


1
@ 2019 i nadal potrzebujemy do tego biblioteki innej firmy: westchnienie:
Adam

2

To nie ma znaczenia. "".equals(str)jest moim zdaniem bardziej jasny.

isEmpty()zwroty count == 0;


47
Powiedziałbym, że str.isEmpty()jest znacznie bardziej jasne niż "".equals(str). To brzmi jak to, co sprawdzasz. Myślę jednak, że to kwestia opinii.
ColinD,

7
Myślę, że niektórzy ludzie wolą robić "" .equals (str), aby uniknąć NPE. Osobiście nie podoba mi się to, ponieważ wolałbym najpierw sprawdzić, czy ciąg nie jest pusty.
CoolBeans

2

Napisałem klasę testera, która może przetestować wydajność:

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

Okazało się, że użycie .isEmpty () zajęło około połowę czasu .equals ("").


To nie jest prawidłowy mikrobenchmark. Zdecydowanie polecam użycie Calipera lub podobnego narzędzia do testów porównawczych. stackoverflow.com/q/504103/139010
Matt Ball

Dzięki za wskazówkę! Kiedy będę miał trochę wolnego czasu, poeksperymentuję z mikro-benchmarkingiem i zaktualizuję swoją odpowiedź.
conapart3
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.