ฉันควรใช้ string.isEmpty () หรือ“” .equals (string) หรือไม่


171

ชื่อโดยทั่วไปบอกว่ามันทั้งหมด ฉันมักจะทดสอบสิ่งนี้ควบคู่กับ a string == nullดังนั้นฉันจึงไม่กังวลเกี่ยวกับการทดสอบที่ปลอดภัย ฉันควรใช้แบบไหน

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

หรือ

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

บนโน้ตนั้น - isEmpty()ทำอะไรอื่นนอกจากreturn this.equals("");หรือreturn this.length() == 0;?


26
โปรดทราบว่าisEmpty()เป็น Java 6+ เท่านั้น
ColinD

1
คุณสามารถสร้างเมธอดตัวช่วยเหลือ Util.String.hasValue (String s) ซึ่งตรวจสอบความว่างเปล่าความว่างเปล่าและช่องว่างเพื่อจัดการทุกกรณี
Cloudanger

5
@ColinD อาจไม่ใช่ปัญหา - J2SE 5.0 เสร็จสิ้นระยะเวลาสิ้นสุดการใช้งานเมื่อไม่นานมานี้
Tom Hawtin - tackline

1
อีกสิ่งที่ควรพิจารณาคือ "" .equals () ใช้ Object เป็นอาร์กิวเมนต์ดังนั้นคุณจะไม่ได้รับข้อผิดพลาดของคอมไพเลอร์หากประเภทอาร์กิวเมนต์เปลี่ยนจาก String เป็นอย่างอื่นดีขึ้นหรือแย่ลง
พอลแจ็คสัน

คำตอบ:


251

ประโยชน์หลักของ"".equals(s)คือคุณไม่จำเป็นต้องมีการตรวจสอบเป็นโมฆะ ( equalsจะตรวจสอบการโต้แย้งและกลับมาfalseถ้ามันเป็นโมฆะ) ซึ่งคุณดูเหมือนจะไม่สนใจ หากคุณไม่ได้กังวลเกี่ยวกับsการเป็นโมฆะ (หรือมิฉะนั้นการตรวจสอบมัน) แน่นอนฉันจะใช้s.isEmpty(); มันแสดงให้เห็นสิ่งที่คุณกำลังตรวจสอบคุณสนใจหรือไม่ว่าsว่างเปล่าไม่ว่ามันจะเท่ากับสตริงว่าง


29
ขอบคุณสำหรับคำอธิบาย ตอนนี้ฉันรู้แล้วว่าทำไมชอบ "" .equals (str) มากกว่า str.equals ("")! ฉันมักจะสงสัยว่าทำไมคนอื่นใช้สิ่งนี้บ่อยครั้ง แต่ไม่ได้คำนึงถึงค่าว่าง ยอดเยี่ยม :-)
Peter Wippermann

10
IMHO ยังจำเป็นต้องมีการตรวจสอบ null ในตัวอย่างข้างต้นเนื่องจากเราคิดว่าเงื่อนไขควรเป็นจริงสำหรับค่า Null s == null || "" .equals
mkorpela

5
@ Master.Aurora ไม่ถ้าgetValue()คืน null คุณจะได้รับ NullPointerException เมื่อtoString()ถูกเรียก
ataulm

12
@RenniePet มันไม่เหมือนมีเวทมนตร์ที่เกี่ยวข้อง ถ้าsเป็นโมฆะคุณไม่สามารถเรียกวิธีการได้ - เป็นโมฆะ ""จะไม่เป็นโมฆะดังนั้นคุณสามารถเรียกใช้วิธีการได้อย่างปลอดภัยและequals()สามารถจัดการกรณีที่อาร์กิวเมนต์เป็นโมฆะ
Michael Mrozek

5
ทราบเกี่ยวกับผลการดำเนินงาน: isEmpty()การตรวจสอบความยาวภายในของอาร์เรย์ส่วนตัวในขณะที่equals(Object anObject)ไม่มากขึ้น (เช่นการตรวจสอบinstanceof) perfromance-wise isEmpty()โดยทั่วไปจะเร็วกว่า
Turing85

82

String.equals("")จริงๆแล้วช้ากว่าการisEmpty()โทร สตริงเก็บตัวแปรนับที่เริ่มต้นในตัวสร้างเนื่องจากสตริงไม่เปลี่ยนรูป

isEmpty() เปรียบเทียบตัวแปร count เป็น 0 ในขณะที่เท่ากับจะตรวจสอบประเภทความยาวสตริงแล้ววนซ้ำสตริงเพื่อเปรียบเทียบว่าขนาดตรงกันหรือไม่

ดังนั้นเพื่อตอบคำถามของคุณisEmpty()จะทำอะไรให้น้อยลงจริง ๆ ! และนั่นเป็นสิ่งที่ดี


3
ฉันคิดว่าในกรณีนี้ความแตกต่างใช้ไม่ได้ จะไม่มีการทำซ้ำข้ามสตริงสำหรับการเปรียบเทียบเนื่องจากขนาดจะไม่ตรงกัน (เว้นแต่ว่าสตริงนั้นว่างเปล่าจริง ๆ แล้วไม่มีอักขระที่จะวนซ้ำไปซ้ำอีก)
Michael Mrozek

2
True แต่เท่ากับคุณต้องมีการตรวจสอบการอ้างอิงก่อนเพื่อดูว่าพวกเขาเป็นวัตถุเดียวกันจากนั้นเป็นอินสแตนซ์ของจากนั้นส่งไปยัง String, การตรวจสอบความยาวและจากนั้นในที่สุดการทำซ้ำ ถ้าสตริงทั้งสองว่างเปล่ามันจะเป็นเพียงการตรวจสอบอ้างอิงอย่างง่าย ๆ
David Young Young

ซอร์สโค้ดไปยังคลาส String สามารถใช้งานได้java2s.com/Open-Source/Java-Document/6.0-JDK-Core/lang/java/…
David Young

1
@David dead link; นี่คือรายการสดหนึ่งdocjar.com/html/api/java/lang/String.java.html#1011
แมตต์บอล

17

สิ่งหนึ่งที่คุณอาจต้องการพิจารณานอกเหนือจากปัญหาอื่น ๆ ที่กล่าวถึงก็isEmpty()คือการนำมาใช้ใน 1.6 ดังนั้นหากคุณใช้คุณจะไม่สามารถเรียกใช้รหัสบน Java 1.5 หรือต่ำกว่าได้


4
นั่นไม่ใช่ข้อกังวลสำหรับฉัน
แมตต์บอล

1
นอกจากนี้คำตอบนี้ตอนนี้ 6 ปีที่ผ่านมา ฉันหวังว่าจะไม่มีใครใช้อะไรที่เก่าแก่เช่น Java 1.5 อีกต่อไป
Misha Nasledov

1
ในความเป็นจริงมีหลายสิ่งที่สามารถแตกหักได้เมื่ออัพเกรดจาวารุ่น มันมีความสำคัญน้อยกว่าสำหรับแอพพลิเคชั่นแบ็คเอนด์ที่ทำงานบนเซิร์ฟเวอร์ขนาดใหญ่ ไลบรารีกราฟิกและกลยุทธ์การรวบรวมขยะมักได้รับผลกระทบจากการอัพเกรด Java หลักและรอง ยิ่งไปกว่านั้นซอฟต์แวร์ไคลเอ็นต์สามารถทำงานบนระบบปฏิบัติการที่หลากหลายและบางครั้งมีหน่วยความจำ จำกัด ซึ่งหมายความว่าคุณมักจะไม่มีงบประมาณ / ทรัพยากรในการทดสอบทุกอย่าง - ใช่ฉันมีลูกค้าที่ยังคงติดตั้ง Java 5 ในปี 2560
bvdb

15

คุณสามารถใช้ apache commons StringUtils isEmpty () หรือ isNotEmpty ()


1
@ 2019 และเรายังต้องการห้องสมุดบุคคลที่สามสำหรับเรื่องนี้: ถอนหายใจ:
อดัม

2

มันไม่สำคัญหรอก "".equals(str)ชัดเจนในความคิดของฉัน

isEmpty()ผลตอบแทนcount == 0;


47
ผมว่าเป็นที่ชัดเจนมากขึ้นกว่าstr.isEmpty() "".equals(str)มันอ่านสิ่งที่คุณกำลังตรวจสอบ แม้ว่าจะมีความคิดเห็นก็ตามฉันเดา
ColinD

7
ฉันคิดว่าบางคนชอบทำ "" .qual (str) "เพื่อหลีกเลี่ยง NPE ฉันไม่ชอบมันเป็นการส่วนตัวเพราะฉันต้องการตรวจสอบว่าสตริงนั้นไม่ว่างก่อน
CoolBeans

2

ฉันเขียนคลาสผู้ทดสอบซึ่งสามารถทดสอบประสิทธิภาพได้:

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

ฉันพบว่าการใช้. isEmpty () ใช้เวลาประมาณครึ่งหนึ่งของ. equals ("")


นี่ไม่ใช่ microbenchmark ที่ถูกต้อง ฉันขอแนะนำอย่างยิ่งให้ใช้Caliperหรือเครื่องมือเปรียบเทียบที่สร้างขึ้นโดยมีจุดประสงค์คล้ายกัน stackoverflow.com/q/504103/139010
แมตต์บอล

ขอบคุณสำหรับทิป! เมื่อฉันได้รับเวลาว่างฉันจะทดสอบด้วยการเปรียบเทียบไมโครและอัปเดตคำตอบของฉัน
conapart3
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.