Sự khác biệt giữa các phương thức String # bằng và String # contentEquals


Câu trả lời:


171

Các String#equals()không chỉ so sánh nội dung của String, mà còn kiểm tra nếu đối tượng khác cũng là một thể hiện của một String. Các String#contentEquals()chỉ so sánh nội dung (chuỗi ký tự) và không không kiểm tra xem đối tượng khác cũng là một thể hiện của String. Nó có thể là bất cứ điều gì miễn là nó là một thực hiện CharSequencetrong đó bao gồm ao String, StringBuilder, StringBuffer, CharBuffervv


12
Vì vậy, nó có giống như các toán tử ==(contentEquals) và ===(bằng) trong javascript không?
anestv

2
@anestv Trong Java, ==toán tử sẽ chỉ cho phép bạn so sánh các tham chiếu không phải là nội dung của hai đối tượng.
Stephan

2
@Alex để làm rõ, toán tử == trong Java là để kiểm tra xem hai đối tượng trỏ đến cùng một vị trí trong bộ nhớ hay hai loại nguyên thủy (byte, short, int, long, float, double, char, boolean) có bằng nhau không.
La-comadreja

2
@Stephan, ==đề cập chỉ là JavaScript; nó không bao giờ được đề cập về Java.
Oledit

@anestv, có sự khác biệt ( ví dụ ==trong JavaScript lỏng hơn nhiều so với contentEquals, chẳng hạn như không chạm vào số), nhưng bạn đã đúng về equalsviệc kiểm tra loại khớp chính xác vớiStrings (các lớp khác có thể lỏng hơn với các loại trong equalsphương thức của chúng ) .
Oledit

43

Nói một cách dễ dàng: String.contentEquals()là người anh em thông minh hơn String.equals(), bởi vì nó có thể tự do hơn trong việc thực hiện hơn String.equals().

Có một số lý do tại sao có một String.contentEquals()phương pháp riêng biệt . Lý do quan trọng nhất tôi nghĩ là:

  • Các equalsphương pháp này phải được phản. Điều đó có nghĩa là : x.equals(y) == y.equals(x). Điều này ngụ ý rằng aString.equals(aStringBuffer)sẽ phải giống như aStringBuffer.equals(aString). Điều này sẽ yêu cầu các nhà phát triển API Java thực hiện một số triển khai đặc biệt cho Chuỗi theo equals()phương thức StringBuffer, StringBuilder và CharSequence. Đây sẽ là một mớ hỗn độn.

Đây là nơi String.contentEqualsđến. Đây là một phương pháp độc lậpkhông phải làm theo các yêu cầu nghiêm ngặt và quy tắc cho Object.equals. Bằng cách này, bạn có thể thực hiện ý nghĩa "nội dung bình đẳng" một cách tự do hơn. Điều này cho phép bạn thực hiện so sánh thông minh giữa StringBuffer và String chẳng hạn.

Và để nói chính xác sự khác biệt là gì:

  • String.contentEquals()có thể so sánh nội dung của a String, a StringBuilder, a StringBuffer, a CharSequencevà tất cả các lớp dẫn xuất của các lớp này. Nếu tham số có kiểu String, thì String.equals()được thực thi.

  • String.equals()chỉ so sánh các đối tượng String. Tất cả các loại đối tượng khác được coi là không bằng nhau.

  • String.contentEquals()có thể so sánh StringBufferStringBuildermột cách thông minh. Nó không gọi toString()phương thức nặng , sao chép toàn bộ nội dung sang một đối tượng String mới. Thay vào đó, nó so sánh với các char[]mảng bên dưới , đó là tuyệt vời.


31

Câu trả lời này đã được đăng bởi dbw nhưng anh ta đã xóa nó nhưng anh ta có một số điểm rất hợp lệ cho sự khác biệt trong khi so sánh thời gian thực hiện, những ngoại lệ nào được đưa ra,

Nếu bạn nhìn vào mã nguồn String # bằngString # contentEquals thì rõ ràng có hai phương thức được ghi đè cho String#contentEqualsmột phương thức lấy StringBuildervà phương thức khác CharSequence.
Sự khác biệt giữa chúng,

  1. String#contentEqualssẽ ném NPE nếu đối số được cung cấp nullnhưng String#equalssẽ trả vềfalse
  2. String#equalschỉ so sánh nội dung khi đối số được cung cấp instance of Stringnếu không nó sẽ trả về falsetrong tất cả các trường hợp khác nhưng mặt khác String#contentEqualskiểm tra nội dung của tất cả các đối tượng thực hiện giao diện CharSequence.
  3. Bạn cũng có thể điều chỉnh mã để String#contentEqualstrả về kết quả sai hoặc kết quả bạn muốn bằng cách ghi đè equalsphương thức của đối số được truyền như dưới đây nhưng bạn không thể thực hiện các chỉnh sửa đó String#equals.
    Mã bên dưới sẽ luôn tạo ratrue miễn là schứa bất kỳ stringký tự nào dài 3 ký tự

        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#contentEqualssẽ chậm hơn String#Equalstrong trường hợp khi đối số được cung cấp là instance of Stringvà độ dài của cả hai Stringlà như nhau nhưng nội dung không bằng nhau.
    Ví dụ nếu chuỗi là String s = "madam"String argPassed = "madan"sau đó s.contentEquals(argPassed)sẽ mất gần gấp đôi thời gian thực hiện trong trường hợp này so vớis.equals(argPassed)

  5. Nếu độ dài nội dung không giống nhau cho cả hai chuỗi thì hàm String#contentEqualssẽ có hiệu suất tốt hơn String#Equalstrong hầu hết các trường hợp có thể.

Thêm một điểm để thêm vào câu trả lời của anh ấy

  1. String#contentEqualscủa một Stringđối tượng cũng sẽ so sánh với StringBuildernội dung và cung cấp kết quả phù hợp trong khi String#Equalssẽ trả vềfalse

4
@dbw câu trả lời này là từ câu trả lời bạn đã đăng
Prateek

@dbw Bên cạnh đó, tại sao bạn lại xóa bài viết của mình?
MC Hoàng đế

14
  • Stringequals(Object o)phương pháp lớp không chỉ Stringso sánh. Nhưng contentEquals(CharSequence cs)kiểm tra cho các lớp học kéo dài AbstractStringBuildertức StringBuffer, StringBuilderStringlớp cũng (Tất cả họ đều là những loại CharSequence).

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

đầu ra:

false
true

Kết quả của stmt đầu tiên là falsebởi vì builderkhông phải là loại Stringđể equals()trở về falsenhưng contentEquals()kiểm tra về nội dung của tất cả các loại như StringBuilder, StringBuffer, Stringvà như nội dung là giống nhau vì thế true.

  • contentEqualssẽ ném NullPointerExceptionnếu đối số được cung cấp là nullnhưng equals()sẽ trả về false vì hàm bằng () kiểm tra instanceOf ( if (anObject instance of String)) trả về false nếu đối số là null.

14

contentEquals(CharSequence cs):

  • Cho phép bạn kiểm tra bình đẳng của chuỗi giá trị được đưa ra với bất kỳ trường hợp thực hiện của giao diện java.lang.CharacterSequence(ví dụ CharBuffer, Segment, String, StringBuffer, StringBuilder)

equals(Object anObject):

  • Cho phép bạn kiểm tra sự bằng nhau của giá trị chuỗi đã cho với bất kỳ trường hợp nào java.lang.String chỉ

RTFC :)

Vì đọc nguồn là cách tốt nhất để hiểu về nó, tôi chia sẻ việc triển khai cả hai phương thức (kể từ 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;
 }

Có một phương thức khác của String # contentEquals ():

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

9

equals()contentEquals()là hai phương thức trong Stringlớp để so sánh hai stringsstringvới StringBuffer.

Các thông số của contentEquals()StringBufferString(charSequence). equals()được sử dụng để so sánh hai stringscontentEquals()được sử dụng để so sánh nội dung của StringStringBuffer.

Phương pháp contentEqualsequals

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

Đây là một mã mô tả cả hai phương thức

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

Đầu ra:

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

7

Chuỗi # bằng lấy đối tượng làm đối số và kiểm tra xem nó có phải là đối tượng của đối tượng Chuỗi hay không. Nếu đối tượng đối số là String Object thì nó so sánh nội dung theo từng ký tự. Nó trả về true trong trường hợp nội dung của cả hai đối tượng chuỗi là như nhau.

Chuỗi # contentEquals lấy giao diện CharSequence làm đối số. CharSequence có thể được thực hiện theo 2 cách - bằng cách sử dụng i) Lớp String hoặc (ii) AbstractStringBuilder (lớp cha của StringBuffer, StringBuilder)

Trong contentEquals () chiều dài được so sánh trước bất kỳ kiểm tra thể hiện đối tượng nào. Nếu độ dài là như nhau thì nó sẽ kiểm tra đối tượng có phải là đối tượng của AbstractStringBuilder hay không. Nếu đúng như vậy (ví dụ StringBuffer hoặc StringBuilder) thì nội dung được kiểm tra theo từng ký tự. Trong trường hợp đối số là một thể hiện của đối tượng String thì String # bằng được gọi từ String # contentEquals.

Vì vậy, trong ngắn hạn,

Chuỗi # bằng so sánh ký tự nội dung theo ký tự trong trường hợp đối số cũng là đối tượng Chuỗi. Và String # contentEquals so sánh nội dung trong trường hợp đối tượng đối số triển khai giao diện CharSequence.

Chuỗi # contentEquals chậm hơn trong trường hợp chúng ta so sánh hai nội dung chuỗi có cùng độ dài như Chuỗi # contentEquals gọi nội bộ Chuỗi # bằng với đối tượng Chuỗi.

Trong trường hợp chúng tôi cố gắng so sánh các đối tượng có độ dài nội dung khác nhau (giả sử "abc" với "abcd") thì String # contentEquals nhanh hơn String # bằng. Bởi vì độ dài được so sánh trước khi bất kỳ đối tượng kiểm tra.


6

Các contentEquals()kiểm tra phương pháp là nội dung là giống nhau giữa một String, StringBuffer, vv mà một số loại chuỗi char.


5

BTW, lý do lịch sử cho sự khác biệt là String ban đầu không có siêu lớp, vì vậy String.equals () lấy String làm đối số của nó. Khi CharSequence được giới thiệu là siêu lớp của Chuỗi, nó cần một phép kiểm tra đẳng thức của chính nó hoạt động trên tất cả các triển khai CharSequence và nó sẽ không va chạm với các chuỗi bằng () đã được sử dụng bởi String ... vì vậy chúng tôi đã nhận được CharSequence.contentEquals ( ), được kế thừa bởi String.

Nếu CharSequence đã có mặt trong Java 1.0, thì chúng tôi sẽ chỉ có CharSequence.equals () và String sẽ thực hiện điều đó.

Ah, niềm vui của ngôn ngữ phát triển ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.