Diferença entre os métodos String # equals e String # contentEquals

Respostas:

171

A String#equals()não só compara o conteúdo da string, mas também verifica se a outro objeto também é uma instância de um String. O String#contentEquals()único compara o conteúdo (a sequência de caracteres) e não verifica se o outro objeto também é uma instância de String. Pode ser qualquer coisa, desde que ele é uma implementação CharSequenceque abrange Ao String, StringBuilder, StringBuffer, CharBuffer, etc.

BalusC
fonte
12
Então, é como os operadores ==(contentEquals) e ===(iguais) em javascript?
anestv
2
@anestv Em Java, o ==operador permitirá apenas comparar as referências e não o conteúdo de dois objetos.
24513 Stephan
2
@Alex para esclarecer, o operador == em Java é para verificar se dois objetos apontam para o mesmo local na memória ou se dois tipos primitivos (byte, short, int, long, float, double, char, boolean) são iguais.
27613 La-comadreja
2
@Stephan, o ==mencionado é apenas JavaScript; isso nunca é mencionado em Java.
quer
@anestv, existem diferenças ( ==em JavaScript é looser longe do que contentEquals, o que não vai tocar números, por exemplo), mas você está correto sobre equalsa verificação de uma partida tipo exato comStrings (outras classes poderia ser mais flexível com os tipos em seus equalsmétodos) .
Olathe
43

Para simplificar: String.contentEquals()é o irmão mais inteligente de String.equals(), porque pode ser mais livre na implementação do que String.equals().

Existem algumas razões pelas quais existe um String.contentEquals()método separado . A razão mais importante que eu acho é:

  • O equalsmétodo deve ser reflexivo. Isso significa que: x.equals(y) == y.equals(x). Isso implica que aString.equals(aStringBuffer)teria que ser o mesmo que aStringBuffer.equals(aString). Isso exigiria que os desenvolvedores da API Java fizessem alguma implementação especial para Strings no equals()método StringBuffer, StringBuilder e CharSequence também. Isso seria uma bagunça.

Isto é onde String.contentEqualsentra. Este é um método autônomo que não não tem que seguir os requisitos e regras estritas para Object.equals. Dessa forma, você pode implementar o senso de "conteúdo igual" mais livremente. Isso permite que você faça comparações inteligentes entre um StringBuffer e um String, por exemplo.

E para dizer qual é exatamente a diferença:

  • String.contentEquals()pode comparar o conteúdo de a String, a StringBuilder, a StringBuffer, a CharSequencee todas as classes derivadas delas. Se o parâmetro for do tipo String, então String.equals()seja executado.

  • String.equals()compara apenas objetos String. Todos os outros tipos de objetos são considerados diferentes.

  • String.contentEquals()pode comparar StringBuffere de StringBuilderforma inteligente. Ele não chama o toString()método pesado , que copia todo o conteúdo para um novo objeto String. Em vez disso, ele se compara à char[]matriz subjacente , o que é ótimo.

Martijn Courteaux
fonte
31

Essa resposta já foi postada pelo dbw, mas ele a excluiu, mas tinha alguns pontos válidos para a diferença ao comparar o tempo de execução, quais exceções são lançadas,

Se você observar o código-fonte String # equals e String # contentEquals , ficará claro que existem dois métodos substituídos para String#contentEqualsum que aceita StringBuildere outro CharSequence.
A diferença entre eles,

  1. String#contentEqualslançará NPE se o argumento fornecido for, nullmas String#equalsretornaráfalse
  2. String#equalscompara o conteúdo apenas quando o argumento fornecido é o instance of Stringcontrário, ele retornará falseem todos os outros casos, mas, por outro lado, String#contentEqualsverifica o conteúdo de todos os objetos que implementam a interface CharSequence.
  3. Você também pode ajustar o código para String#contentEqualsretornar o resultado errado ou o resultado desejado, substituindo o equalsmétodo do argumento passado conforme mostrado abaixo, mas não pode fazer esses ajustes String#equals.
    O código abaixo sempre produzirátrue contanto que scontenha string3 caracteres

        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#contentEqualsserá mais lento que String#Equalso argumento fornecido instance of Stringe o comprimento de ambos Stringserá o mesmo, mas o conteúdo não será igual.
    Exemplo se a string for String s = "madam"e, em String argPassed = "madan"seguida s.contentEquals(argPassed), levará quase o dobro do tempo de execução nesse caso, em comparação coms.equals(argPassed)

  5. Se o comprimento do conteúdo não for o mesmo para as duas cadeias, a função String#contentEqualsterá melhor desempenho do que String#Equalsem quase todos os casos possíveis.

Mais um ponto a acrescentar à sua resposta

  1. String#contentEqualsde um Stringobjeto também será comparado ao StringBuilderconteúdo e fornecerá o resultado apropriado enquanto String#Equalsretornaráfalse
Prateek
fonte
4
@dbw esta resposta é a partir da resposta que você postou
Prateek
@dbw Além disso, por que você excluiu sua postagem?
MC Emperor
14
  • StringO equals(Object o)método de classe faz apenas Stringcomparação. Mas as contentEquals(CharSequence cs)verificações de classes se estendem , AbstractStringBuilderou seja StringBuffer, StringBuildere Stringtambém de classe (todas elas são do tipo CharSequence).

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

resultado:

false
true

A saída do primeiro stmt é falseporque buildernão é do tipo, Stringentão equals()retorna, falsemas contentEquals()verifica o conteúdo de todo o tipo StringBuilder, como StringBuffer, Stringe como o conteúdo é o mesmo true.

  • contentEqualsjogará NullPointerExceptionse o argumento fornecido for, nullmas equals()retornará false, porque o equals () verifica instanceOf ( if (anObject instance of String)) que retorna false se o argumento for null.
Tentando
fonte
14

contentEquals(CharSequence cs):

  • Permite verificar a igualdade de determinado valor de string com qualquer instância implementação de interface de java.lang.CharacterSequence(por exemplo, CharBuffer, Segment, String, StringBuffer, StringBuilder)

equals(Object anObject):

  • Permite verificar a igualdade de determinado valor de string com qualquer instância do tipo java.lang.String única

RTFC :)

Como ler a fonte é a melhor maneira de entendê-la, estou compartilhando as implementações dos dois métodos (a partir do 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;
 }

Há outro método da String # contentEquals ():

public boolean contentEquals(StringBuffer sb) {
    synchronized(sb) {
        return contentEquals((CharSequence)sb);
    }
}
Amit Sharma
fonte
9

equals()e contentEquals()são dois métodos na Stringclasse para comparar dois stringse stringcom StringBuffer.

Os parâmetros de contentEquals()são StringBuffere String(charSequence). equals()é usado para comparar dois stringse contentEquals()é usado para comparar o conteúdo de Stringe StringBuffer.

Método contentEqualse equalssão

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

Aqui está um código que descreve os dois métodos

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

Resultado:

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

String # equals usa Object como argumento e verifica se é uma instância do objeto String ou não. Se o objeto do argumento for String Object, ele compara o conteúdo caracter por caracter. Retorna true caso o conteúdo dos dois objetos de string seja o mesmo.

A sequência # contentEquals usa a interface CharSequence como argumento. CharSequence pode ser implementado de duas maneiras - usando i) classe String ou (ii) AbstractStringBuilder (classe pai de StringBuffer, StringBuilder)

Em contentEquals (), o comprimento é comparado antes de qualquer verificação da instância do objeto. Se o comprimento for o mesmo, ele verifica se o objeto do argumento é uma instância do AbstractStringBuilder ou não. Se assim for (por exemplo, StringBuffer ou StringBuilder), o conteúdo é verificado, caractere por caractere. Caso o argumento seja uma instância do objeto String, a String # é igual a chamada da String # contentEquals.

Então, resumindo,

String # equals compara o caractere de conteúdo por caractere, caso o argumento também seja objeto de String. E String # contentEquals compara o conteúdo caso o objeto de argumento implemente a interface CharSequence.

String # contentEquals é mais lenta, caso comparemos dois conteúdos de string com o mesmo comprimento que String # contentEquals chama internamente String # igual a para o objeto String.

Caso tentemos comparar objetos com diferentes tamanhos de conteúdo (digamos "abc" com "abcd"), a String # contentEquals é mais rápida que a String # igual. Porque o comprimento é comparado antes de qualquer verificação de instância do objeto.

Anirban Pal
fonte
6

Os contentEquals()método verifica se os conteúdos são os mesmos entre um String, StringBuffer, etc, que algum tipo de sequcia de carvão animal.

fastcodejava
fonte
5

BTW, a razão histórica para a diferença é que String originalmente não tinha superclasse, então String.equals () usa uma String como argumento. Quando o CharSequence foi introduzido como a superclasse de String, ele precisava de um teste de igualdade próprio que funcionasse em todas as implementações do CharSequence e que não colidisse com os equals () já em uso pelo String ... então obtivemos CharSequence.contentEquals ( ), que é herdado por String.

Se CharSequence estivesse presente no Java 1.0, provavelmente teríamos apenas CharSequence.equals () e String simplesmente implementaria isso.

Ah, as alegrias das línguas em evolução ...

keshlam
fonte