Разница между методами String # equals и String # contentEquals - PullRequest
125 голосов
/ 25 июня 2011

В чем разница между методом String#equals и методом String#contentEquals?

Ответы [ 9 ]

141 голосов
/ 25 июня 2011

String#equals() не только сравнивает содержимое строки, но также проверяет, является ли другой объект также экземпляром String. String#contentEquals() сравнивает только содержимое (последовательность символов) и не проверяет, является ли другой объект также экземпляром String. Это может быть что угодно, только если это реализация CharSequence, которая охватывает a.o. String, StringBuilder, StringBuffer, CharBuffer и т. Д.

34 голосов
/ 25 декабря 2013

Проще говоря: String.contentEquals() - умный брат String.equals(), потому что он может быть более свободным в реализации, чем String.equals().

Есть несколько причин, по которым существует отдельный String.contentEquals() метод. Я думаю, что самая важная причина:

  • Метод equals должен быть рефлексивным. Это означает, что: x.equals(y) == y.equals(x). Это означает, что aString.equals(aStringBuffer) должно быть таким же, как aStringBuffer.equals(aString). Это потребует от разработчиков Java API создания специальной реализации для строк в методе equals() StringBuffer, StringBuilder и CharSequence. Это было бы беспорядок.

Итак, вот когда наступает String.contentEquals. Это автономный метод , который не должен следовать строгим требованиям и правилам для Object.equals. Таким образом, вы можете более свободно реализовать смысл «равного содержания» . Это позволяет вам делать интеллектуальные сравнения между StringBuffer и String, например.

И сказать, в чем именно разница:

  • String.contentEquals() может сравнивать содержимое String, StringBuilder, StringBuffer, CharSequence и всех их производных классов. Если параметр имеет тип String, то выполняется String.equals().

  • String.equals() сравнивает только строковые объекты. Все остальные типы объектов считаются не равными.

  • String.contentEquals() может разумно сравнить StringBuffer и StringBuilder. Он не вызывает тяжелый метод toString(), который копирует все содержимое в новый объект String. Вместо этого он сравнивается с базовым массивом char[], что отлично.

28 голосов
/ 26 декабря 2013

Этот ответ уже был опубликован dbw , но он удалил его, но у него было несколько очень точных точек для разницы при сравнении времени выполнения, какие исключения выбрасываются,

Если вы посмотрите на исходный код String # равно и String # contentEquals , то ясно, что для String#contentEquals есть два переопределенных метода, один из которых принимает StringBuilder, а другой CharSequence.
Разница между ними

  1. String#contentEquals сгенерирует NPE, если задан аргумент null, но String#equals вернет false
  2. String#equals сравнивает содержимое только тогда, когда задан аргумент instance of String, в противном случае он вернет false во всех других случаях, но с другой стороны String#contentEquals проверяет содержимое всех объектов, которые реализуют интерфейс CharSequence.
  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
13 голосов
/ 24 декабря 2013

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);
    }
}
10 голосов
/ 24 декабря 2013
  • String класс equals(Object o) метод делает только String сравнение. Но contentEquals(CharSequence cs) проверки для классов расширяют AbstractStringBuilder, то есть StringBuffer, StringBuilder и String class также (все они имеют тип 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, String и так как содержание то же самое, следовательно true.

  • contentEquals сгенерирует NullPointerException, если задан аргумент null, но equals() вернет false, потому что equals () проверяет instanceOf (if (anObject instance of String)), который возвращает false, если аргумент null.
8 голосов
/ 25 декабря 2013

equals() и contentEquals() - два метода в классе String для сравнения двух strings и string с StringBuffer.

Параметры contentEquals(): StringBuffer и String(charSequence). equals() используется для сравнения двух strings и contentEquals() используется для сравнения содержимого String и StringBuffer.

Метод 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
6 голосов
/ 28 декабря 2013

String # равно принимает Object в качестве аргумента и проверяет, является ли он экземпляром объекта String или нет.Если аргументом является объект String, он сравнивает содержимое символ за символом.Он возвращает true, если содержимое обоих строковых объектов одинаково.

String # contentEquals принимает в качестве аргумента интерфейс CharSequence.CharSequence может быть реализован двумя способами - используя i) класс String или (ii) AbstractStringBuilder (родительский класс StringBuffer, StringBuilder)

In Длина contentEquals () сравнивается перед любым экземпляром объектапроверять.Если длина одинакова, то проверяется, является ли объект аргумента экземпляром AbstractStringBuilder или нет.Если это так (т.е. StringBuffer или StringBuilder), то содержимое проверяется посимвольно.Если аргумент является экземпляром объекта String, то String # equals вызывается из String # contentEquals.

Короче говоря,

String # равно сравнивает содержимое символ за символомв случае, если аргумент также является объектом String.И String # contentEquals сравнивает содержимое в случае, если объект-аргумент реализует интерфейс CharSequence.

String # contentEquals медленнее, если мы сравниваем два строковых содержимого одинаковой длины, так как String # contentEquals внутренне вызывает String #, равнодля строкового объекта.

Если мы попытаемся сравнить объекты с разной длиной содержимого (скажем, «abc» с «abcd»), то String # contentEquals будет быстрее, чем String # равно.Потому что длина сравнивается перед проверкой экземпляра объекта.

6 голосов
/ 25 июня 2011

Метод contentEquals() проверяет, является ли содержимое одинаковым между String, StringBuffer и т. Д., Которые имеют какую-то последовательность символов.

5 голосов
/ 27 декабря 2013

Кстати, историческая причина разницы в том, что String изначально не имел суперкласса, поэтому String.equals () принимает String в качестве аргумента. Когда CharSequence был представлен в качестве суперкласса String, он нуждался в собственном тесте на равенство, который работал бы во всех реализациях CharSequence, и который не конфликтовал бы с equals (), уже используемым String ... поэтому мы получили CharSequence.contentEquals ( ), который наследуется String.

Если бы CharSequence присутствовал в Java 1.0, мы, вероятно, имели бы только CharSequence.equals (), и String просто реализовал бы это.

Ах, радости развивающихся языков ...

...