Haruskah saya menggunakan string.isEmpty () atau "" .equals (string)?

171

Judul pada dasarnya mengatakan itu semua. Saya biasanya menguji ini bersama a string == null, jadi saya tidak benar-benar khawatir tentang tes nol-aman. Yang mana yang harus saya gunakan?

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

atau

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

Pada catatan itu - isEmpty()bahkan tidak melakukan apa pun selain return this.equals("");atau return this.length() == 0;?

Matt Ball
sumber
26
Perlu diingat bahwa isEmpty()itu hanya Java 6+.
ColinD
1
Anda bisa membuat metode pembantu Util.String.hasValue (String s) yang memeriksa null, kekosongan dan spasi untuk menangani semua kasus.
Cloudanger
5
@ColinD Mungkin bukan masalah - J2SE 5.0 menyelesaikan periode Akhir Masa Layanannya beberapa waktu lalu.
Tom Hawtin - tackline
1
Hal lain yang perlu dipertimbangkan adalah "" .equals () mengambil Object sebagai argumen, jadi Anda tidak akan mendapatkan kesalahan kompilator jika tipe argumen berubah dari String ke sesuatu yang lain, baik atau buruk.
Paul Jackson

Jawaban:

251

Manfaat utama "".equals(s)adalah Anda tidak perlu cek nol ( equalsakan memeriksa argumennya dan kembali falsejika itu nol), yang tampaknya tidak Anda pedulikan. Jika Anda tidak khawatir smenjadi nol (atau memeriksanya), saya pasti akan menggunakan s.isEmpty(); itu menunjukkan dengan tepat apa yang Anda periksa, Anda peduli skosong atau tidak , tidak sama dengan string kosong

Michael Mrozek
sumber
29
Terima kasih atas penjelasannya. Sekarang saya tahu mengapa memilih "" .equals (str) di atas str.equals ("")! Saya selalu bertanya-tanya mengapa orang lain sering menggunakan ini, tetapi tidak memperhitungkan nilai nol. Hebat :-)
Peter Wippermann
10
IMHO pemeriksaan nol masih diperlukan dalam contoh di atas karena kami menganggap bahwa kondisi tersebut harus benar untuk nilai nol. s == null || "". equals (s)
mkorpela
5
@ Master.Aurora tidak, jika getValue()dikembalikan nol, Anda akan mendapatkan NullPointerException ketika toString()dipanggil
ataulm
12
@RenniePet Ini tidak seperti ada sihir yang terlibat. Jika snol, Anda tidak dapat memanggil metode di dalamnya - itu nol. ""tidak akan pernah menjadi nol, sehingga Anda dapat memanggil metode di dalamnya dengan aman, dan equals()dapat menangani kasus di mana argumennya nol
Michael Mrozek
5
Catatan tentang kinerja: isEmpty()memeriksa panjang internal array pribadi sementara equals(Object anObject)melakukan lebih banyak lagi (misalnya memeriksa instanceof). Dari segi perfromance, isEmpty()umumnya lebih cepat.
Turing85
82

String.equals("")sebenarnya sedikit lebih lambat dari sekedar isEmpty()panggilan. Strings menyimpan variabel count yang diinisialisasi dalam konstruktor, karena String tidak dapat diubah.

isEmpty() membandingkan variabel jumlah ke 0, sedangkan yang sama akan memeriksa jenis, panjang string, dan kemudian beralih pada string untuk perbandingan jika ukurannya cocok.

Jadi untuk menjawab pertanyaan Anda, isEmpty()sebenarnya akan melakukan jauh lebih sedikit! dan itu hal yang baik.

David Young
sumber
3
Saya pikir dalam hal ini perbedaannya tidak berlaku; tidak akan pernah ada iterasi di atas string untuk perbandingan, karena ukurannya tidak akan cocok (kecuali string benar-benar kosong, dan kemudian tidak ada karakter untuk diulangi)
Michael Mrozek
2
Benar tetapi dengan sama dengan Anda dikenakan pemeriksaan referensi pertama untuk melihat apakah mereka adalah objek yang sama, lalu instanceof, kemudian dilemparkan ke String, cek panjang, dan akhirnya iterasi. Jika kedua Strings kosong maka itu akan menjadi hanya pemeriksaan referensi sederhana.
David Young
kode sumber ke kelas String tersedia java2s.com/Open-Source/Java-Document/6.0-JDK-Core/lang/java/…
David Young
1
@ Menghubungkan tautan mati; inilah live satu docjar.com/html/api/java/lang/String.java.html#1011
Matt Ball
17

Satu hal yang mungkin ingin Anda pertimbangkan selain masalah lain yang disebutkan adalah yang isEmpty()diperkenalkan pada 1.6, jadi jika Anda menggunakannya Anda tidak akan dapat menjalankan kode di Java 1.5 atau di bawah.

Fabian Steeg
sumber
4
Itu jelas bukan masalah bagi saya.
Matt Ball
1
Juga, jawaban ini sekarang 6 tahun yang lalu. Saya berharap tidak ada yang harus menggunakan sesuatu yang kuno seperti Java 1.5 lagi.
Misha Nasledov
1
Sebenarnya ada banyak hal yang dapat rusak ketika meningkatkan versi java. Ini kurang penting untuk aplikasi back-end yang berjalan di server besar, tetapi itu penting untuk aplikasi klien. Perpustakaan grafis dan strategi pengumpulan sampah sering dipengaruhi oleh peningkatan java besar dan kecil. Selain itu, perangkat lunak klien dapat berjalan di berbagai sistem operasi dan kadang-kadang dengan memori terbatas, yang berarti Anda sering tidak memiliki anggaran / sumber daya untuk menguji semuanya. - Ya, saya memiliki pelanggan yang masih menggunakan Java 5 pada 2017.
bvdb
15

Anda dapat menggunakan apache commons StringUtils isEmpty () atau isNotEmpty ().

CoolBeans
sumber
1
@ 2019 dan kami masih membutuhkan perpustakaan pihak ke-3 untuk ini: huh:
Adam
2

Itu tidak masalah. "".equals(str)lebih jelas menurut saya.

isEmpty()pengembalian count == 0;

Kylar
sumber
47
Menurut saya str.isEmpty()jauh lebih jelas daripada "".equals(str). Bunyinya seperti apa yang Anda periksa. Soal pendapat, saya kira.
ColinD
7
Saya pikir beberapa orang lebih suka melakukan "". Sama dengan (str) untuk menghindari NPE. Saya pribadi tidak suka karena saya lebih suka memeriksa string tidak nol terlebih dahulu.
CoolBeans
2

Saya menulis kelas penguji yang dapat menguji kinerja:

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

Saya menemukan bahwa menggunakan .isEmpty () membutuhkan waktu separuh waktu .equals ("").

conapart3
sumber
Ini bukan microbenchmark yang valid. Saya akan sangat menyarankan menggunakan Caliper atau alat pembandingan yang dibuat khusus. stackoverflow.com/q/504103/139010
Matt Ball
Terima kasih atas tipnya! Ketika saya mendapatkan waktu luang saya akan bereksperimen dengan beberapa pembandingan mikro dan memperbarui jawaban saya.
conapart3