ความแตกต่างระหว่างเมธอด String # เท่ากับและ String # contentEquals


คำตอบ:


171

String#equals()ไม่เพียง แต่เปรียบเทียบเนื้อหา String แต่ยังตรวจสอบว่าวัตถุอื่น ๆ Stringยังเป็นตัวอย่างของ String#contentEquals()เปรียบเทียบเฉพาะเนื้อหา (ลำดับตัวอักษร) และไม่ได้ตรวจสอบว่าวัตถุอื่น ๆ Stringยังเป็นตัวอย่างของ มันสามารถเป็นอะไรก็ได้ตราบเท่าที่มันคือการดำเนินการCharSequenceซึ่งครอบคลุมอ่าวString, StringBuilder, StringBuffer, CharBufferฯลฯ


12
ดังนั้นมันเหมือนกับตัวดำเนินการ==(contentEquals) และ===(เท่ากับ) ใน javascript หรือไม่
anestv

2
@anestv ใน Java ตัว==ดำเนินการจะอนุญาตให้คุณเปรียบเทียบการอ้างอิงไม่ใช่เนื้อหาของวัตถุสองรายการ
เตฟาน

2
@Alex เพื่อชี้แจงตัวดำเนินการ == ใน Java ใช้สำหรับตรวจสอบว่ามีวัตถุสองชนิดที่ชี้ไปยังตำแหน่งเดียวกันในหน่วยความจำหรือไม่ว่าจะเป็นประเภทดั้งเดิมสองประเภท (ไบต์สั้น int int ยาวยาวลอยคู่ถ่านบูลีน) เท่ากัน
La-comadreja

2
@Stephan ==กล่าวถึงคือ JavaScript เท่านั้น มันไม่เคยพูดถึงเกี่ยวกับ Java
Olathe

@anestv มีความแตกต่าง ( ==ใน JavaScript มีความคลาดเคลื่อนมากกว่าcontentEqualsซึ่งจะไม่แตะหมายเลข) แต่คุณถูกต้องเกี่ยวกับการequalsตรวจสอบการจับคู่ประเภทที่แน่นอนด้วยStrings (คลาสอื่น ๆ อาจจะหลวมกว่าด้วยequalsวิธีการของพวกเขา) .
Olathe

43

ที่จะนำมันได้อย่างง่ายดาย: String.contentEquals()เป็นพี่ชายชาญฉลาดเพราะมันสามารถเป็นอิสระมากขึ้นในการดำเนินงานมากกว่าString.equals()String.equals()

มีสาเหตุบางประการที่มีString.contentEquals()วิธีแยกต่างหาก เหตุผลที่สำคัญที่สุดที่ฉันคิดคือ:

  • equalsวิธีการจะต้องมีการสะท้อนกลับ นั่นหมายความว่า: x.equals(y) == y.equals(x). นี่ก็หมายความว่าจะต้องเป็นเช่นเดียวกับaString.equals(aStringBuffer) aStringBuffer.equals(aString)สิ่งนี้จะต้องใช้นักพัฒนา Java API เพื่อให้มีการใช้งานพิเศษสำหรับ Strings ในequals()วิธีการของ StringBuffer, StringBuilder และ CharSequence เช่นกัน นี่จะเป็นระเบียบ

นี่คือที่String.contentEqualsมาใน. นี้เป็นวิธีการแบบสแตนด์อโลนที่ไม่ได้มีการปฏิบัติตามข้อกำหนดที่เข้มงวดและกฎระเบียบObject.equalsสำหรับ ด้วยวิธีนี้คุณสามารถใช้ความรู้สึกของ"เนื้อหาเท่ากัน"ได้อย่างอิสระมากขึ้น สิ่งนี้ช่วยให้คุณทำการเปรียบเทียบอย่างชาญฉลาดระหว่าง StringBuffer และสตริงตัวอย่างเช่น

และจะพูดในสิ่งที่แตกต่างคือ:

  • String.contentEquals()สามารถเปรียบเทียบเนื้อหาของ a String, a StringBuilder, a StringBuffer, a CharSequenceและคลาสที่ได้รับทั้งหมดของสิ่งเหล่านี้ หากพารามิเตอร์เป็นประเภท String ให้String.equals()ทำการเรียกใช้งาน

  • String.equals()เปรียบเทียบวัตถุสตริงเท่านั้น วัตถุประเภทอื่น ๆ ทั้งหมดถือว่าไม่เท่ากัน

  • String.contentEquals()สามารถเปรียบเทียบStringBufferและStringBuilderในวิธีที่ชาญฉลาด มันไม่ได้เรียกtoString()วิธีหนักซึ่งคัดลอกเนื้อหาทั้งหมดไปยังวัตถุ String ใหม่ แต่จะเปรียบเทียบกับchar[]อาเรย์พื้นฐานซึ่งยอดเยี่ยม


31

คำตอบนี้ถูกโพสต์แล้วโดยdbwแต่เขาลบมันออกไป แต่เขาก็มีบางจุดที่ถูกต้องมากสำหรับความแตกต่างในขณะที่เปรียบเทียบเวลาดำเนินการข้อยกเว้นที่ถูกโยน

ถ้าคุณดูที่รหัสที่มาเท่ากับสตริง #และString # contentEqualsเป็นที่ชัดเจนว่ามีสองวิธีแทนที่สำหรับString#contentEqualsหนึ่งซึ่งใช้เวลาและอื่น ๆStringBuilder ความแตกต่างระหว่างพวกเขาCharSequence

  1. String#contentEqualsจะโยน NPE หากข้อโต้แย้งที่ให้มามีnullแต่String#equalsจะกลับมาfalse
  2. String#equalsเปรียบเทียบเนื้อหาเฉพาะเมื่ออาร์กิวเมนต์ที่จัดมาให้เป็นinstance of Stringอย่างอื่นก็จะกลับมาfalseในกรณีอื่น ๆ ทั้งหมด แต่ในมืออื่น ๆการตรวจสอบเนื้อหาของวัตถุทั้งหมดที่ใช้อินเตอร์เฟซString#contentEqualsCharSequence
  3. คุณสามารถปรับแต่งรหัสเพื่อให้String#contentEqualsส่งคืนผลลัพธ์ที่ไม่ถูกต้องหรือผลลัพธ์ที่คุณต้องการโดยแทนที่equalsวิธีการโต้แย้งที่ส่งผ่านตามที่แสดงด้านล่าง แต่คุณไม่สามารถปรับแต่งค่าเหล่านั้นString#equalsได้
    โค้ดด้านล่างจะสร้างtrueตราบsใดstringที่มีอักขระใด ๆที่มีความยาว 3 อักขระ

        String s= new String("abc");// "abc";
        System.out.println(s.contentEquals(new CharSequence() 
        {
    
            @Override
            public CharSequence subSequence(int arg0, int arg1) {
                // TODO Auto-generated method stub
                return null;
            }
    
            @Override
            public int length() {
                // TODO Auto-generated method stub
                return 0;
            }
    
            @Override
            public char charAt(int arg0) {
                // TODO Auto-generated method stub
                return 0;
            }
    
    
            @Override
            public boolean equals(Object obj) 
            {
               return true;
            }
        }));
  4. String#contentEqualsจะช้าลงString#Equalsในกรณีที่อาร์กิวเมนต์ที่ให้มามีinstance of StringความยาวStringเท่ากัน แต่เนื้อหาไม่เท่ากัน
    ตัวอย่างเช่นถ้าสตริงString s = "madam"และString argPassed = "madan"จากนั้นs.contentEquals(argPassed)จะใช้เวลาในการดำเนินการเกือบสองเท่าในกรณีนี้เมื่อเทียบกับs.equals(argPassed)

  5. หากความยาวเนื้อหาไม่เหมือนกันสำหรับทั้งสองสตริงฟังก์ชันString#contentEqualsจะมีประสิทธิภาพที่ดีกว่าString#Equalsในเกือบทุกกรณีที่เป็นไปได้

อีกหนึ่งจุดที่จะเพิ่มคำตอบของเขา

  1. String#contentEqualsของStringวัตถุจะเปรียบเทียบกับStringBuilderเนื้อหาและให้ผลลัพธ์ที่เหมาะสมในขณะที่String#Equalsจะกลับมาfalse

4
@dbw คำตอบนี้มาจากคำตอบที่คุณโพสต์
Prateek

@dbw นอกจากนี้ทำไมคุณถึงลบโพสต์ของคุณ
พิธีกรจักรพรรดิ

14
  • Stringequals(Object o)วิธีการเรียนไม่Stringเปรียบเทียบเท่านั้น แต่contentEquals(CharSequence cs)การตรวจสอบสำหรับการเรียนขยายAbstractStringBuilderเช่น StringBuffer, StringBuilderและStringชั้นยัง (พวกเขาทั้งหมดเป็นประเภทCharSequence)

    String str = "stackoverflow";
    StringBuilder builder = new StringBuilder(str);
    System.out.println(str.equals(builder));
    System.out.println(str.contentEquals(builder));

เอาท์พุท:

false
true

เอาต์พุตของ stmt แรกเป็นfalseเพราะbuilderไม่ใช่ชนิดStringเพื่อให้equals()ผลตอบแทนfalseแต่contentEquals()การตรวจสอบเนื้อหาของทุกประเภทเช่นที่StringBuilder, StringBuffer, และเป็นเนื้อหาเดียวกันด้วยเหตุนี้Stringtrue

  • contentEqualsจะโยนNullPointerExceptionหากอาร์กิวเมนต์ที่ให้มาnullแต่equals()จะกลับเท็จเพราะเท่ากับ () ตรวจสอบ instanceOf (if (anObject instance of String) ) nullซึ่งผลตอบแทนที่เป็นเท็จถ้าอาร์กิวเมนต์เป็น

14

contentEquals(CharSequence cs):

  • ช่วยให้คุณตรวจสอบความเท่าเทียมกันของค่าสตริงที่กำหนดด้วยเช่นการดำเนินการใด ๆ ของอินเตอร์เฟซjava.lang.CharacterSequence(เช่นCharBuffer, Segment, String, StringBuffer, StringBuilder)

equals(Object anObject):

  • ให้คุณตรวจสอบความเท่าเทียมกันของค่าสตริงที่กำหนดด้วยอินสแตนซ์ประเภทใด ๆjava.lang.String เท่านั้น

RTFC :)

เนื่องจากการอ่านแหล่งข้อมูลเป็นวิธีที่ดีที่สุดในการทำความเข้าใจฉันกำลังแบ่งปันการใช้งานของทั้งสองวิธี (เช่น jdk 1.7.0_45)

public boolean contentEquals(CharSequence cs) {
    if (value.length != cs.length())
        return false;
    // Argument is a StringBuffer, StringBuilder
    if (cs instanceof AbstractStringBuilder) {
        char v1[] = value;
        char v2[] = ((AbstractStringBuilder) cs).getValue();
        int i = 0;
        int n = value.length;
        while (n-- != 0) {
            if (v1[i] != v2[i])
                return false;
            i++;
        }
        return true;
    }
    // Argument is a String
    if (cs.equals(this))
        return true;
    // Argument is a generic CharSequence
    char v1[] = value;
    int i = 0;
    int n = value.length;
    while (n-- != 0) {
        if (v1[i] != cs.charAt(i))
            return false;
        i++;
    }
    return true;
}

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String) anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                        return false;
                i++;
            }
            return true;
        }
    }
    return false;
 }

มีวิธีอื่นของ String # contentEquals ():

public boolean contentEquals(StringBuffer sb) {
    synchronized(sb) {
        return contentEquals((CharSequence)sb);
    }
}

9

equals()และcontentEquals()มีสองวิธีการในStringชั้นเรียนเพื่อเปรียบเทียบสองstringsและมีstringStringBuffer

พารามิเตอร์ของcontentEquals()Are และStringBuffer ใช้เพื่อเปรียบเทียบสองรายการและใช้เพื่อเปรียบเทียบเนื้อหาของและString(charSequence)equals()stringscontentEquals()StringStringBufferและ

วิธีการcontentEqualsและ equalsก็

public boolean contentEquals(java.lang.StringBuffer);
public boolean contentEquals(java.lang.CharSequence);
public boolean equals(Object o)

นี่คือรหัสที่อธิบายถึงทั้งสองวิธี

public class compareString {
    public static void main(String[] args) {
        String str1 = "hello";    
        String str2 = "hello";

        StringBuffer sb1 = new StringBuffer("hello");
        StringBuffer sb2 = new StringBuffer("world");

        boolean result1 = str1.equals(str2);        // works nice and returns true
        System.out.println(" str1.equals(str2) - "+ result1);

        boolean result2 = str1.equals(sb1);         // works nice and returns false
        System.out.println(" str1.equals(sb1) - "+ result2);

        boolean result3 = str1.contentEquals(sb1);  // works nice and returns true
        System.out.println(" str1.contentEquals(sb1) - "+ result3);

        boolean result4 = str1.contentEquals(sb2);  // works nice and returns false
        System.out.println(" str1.contentEquals(sb2) - "+ result4);

        boolean result5 = str1.contentEquals(str2);  // works nice and returns true
        System.out.println(" str1.contentEquals(str2) - "+ result5);
    }
}

เอาท์พุท:

 str1.equals(str2) - true
 str1.equals(sb1) - false
 str1.contentEquals(sb1) - true
 str1.contentEquals(sb2) - false
 str1.contentEquals(str2) - true

7

String # เท่ากับใช้ Object เป็นอาร์กิวเมนต์และตรวจสอบว่าเป็นอินสแตนซ์ของ String วัตถุหรือไม่ หากวัตถุอาร์กิวเมนต์เป็นวัตถุสตริงก็จะเปรียบเทียบตัวละครเนื้อหาโดยตัวละคร มันจะคืนค่าจริงในกรณีเนื้อหาของวัตถุสตริงทั้งสองเหมือนกัน

String # contentEqualsใช้ CharSequence อินเตอร์เฟสเป็นอาร์กิวเมนต์ CharSequence สามารถใช้งานได้ 2 วิธีโดยใช้ i) String class หรือ (ii) AbstractStringBuilder (คลาสพาเรนต์ของ StringBuffer, StringBuilder)

ในcontentEquals () ความยาวถูกเปรียบเทียบก่อนการตรวจสอบอินสแตนซ์ของวัตถุใด ๆ ถ้าความยาวเท่ากันก็จะตรวจสอบว่าวัตถุนั้นเป็นตัวอย่างของ AbstractStringBuilder หรือไม่ ถ้าเป็นเช่นนั้น (เช่น StringBuffer หรือ StringBuilder) เนื้อหาจะถูกตรวจสอบตัวอักษรโดยตัวละคร ในกรณีที่อาร์กิวเมนต์เป็นตัวอย่างของวัตถุ String แล้ว String # เท่ากับเรียกจาก String # contentEquals

ดังนั้นในระยะสั้น

String # เท่ากับเปรียบเทียบตัวละครเนื้อหาโดยตัวละครในกรณีที่อาร์กิวเมนต์เป็นวัตถุสตริงเช่นกัน และString # contentEqualsเปรียบเทียบเนื้อหาในกรณีที่วัตถุอาร์กิวเมนต์ใช้อินเตอร์เฟซ CharSequence

String # contentEquals ช้าลงในกรณีที่เราเปรียบเทียบเนื้อหาสตริงที่มีความยาวเท่ากันสองรายการเป็น String # contentEquals จะเรียก String # เท่ากับภายในสำหรับ String วัตถุ

ในกรณีที่เราพยายามเปรียบเทียบวัตถุที่มีความยาวเนื้อหาต่างกัน (พูดว่า "abc" กับ "abcd") ดังนั้น String # contentEquals จะเร็วกว่า String # เท่ากับ เนื่องจากมีการเปรียบเทียบความยาวก่อนการตรวจสอบวัตถุใด ๆ


6

contentEquals()ตรวจสอบวิธีการนี้เป็นเนื้อหาจะเหมือนกันระหว่างString, StringBufferฯลฯ ซึ่งชนิดของลำดับถ่านบาง


5

BTW เหตุผลทางประวัติศาสตร์สำหรับความแตกต่างคือสตริงเดิมไม่มีซูเปอร์คลาสดังนั้น String.equals () รับสตริงเป็นอาร์กิวเมนต์ เมื่อ CharSequence ถูกนำมาใช้เป็น superclass ของ String มันจำเป็นต้องมีการทดสอบความเท่าเทียมกันของตัวเองที่ทำงานในทุกการใช้งาน CharSequence และที่จะไม่ชนกับ equals () ที่ใช้งานโดย String ... ดังนั้นเราจึงได้ CharSequence.contentEquals ( ) ซึ่งสืบทอดโดย String

หาก CharSequence มีอยู่ใน Java 1.0 เราก็จะมีเพียง CharSequence.equals () และ String จะใช้มันเพียงอย่างเดียว

อ่าความสุขของการพัฒนาภาษา ...

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