Diferencia entre String # equals y String # contentEquals métodos

Respuestas:

171

El String#equals()no solo compara el contenido de la Cadena, sino que también comprueba si el otro objeto también es una instancia de a String. El String#contentEquals()único compara el contenido (la secuencia de caracteres) y no comprueba si el otro objeto también es una instancia de String. Puede ser cualquier cosa, siempre y cuando se trata de una aplicación de CharSequencela que cubre ao String, StringBuilder, StringBuffer, CharBuffer, etc.

BalusC
fuente
12
Entonces, ¿es como los operadores ==(contentEquals) y ===(equals) en javascript?
anestv
2
@anestv En Java, el ==operador solo le permitirá comparar las referencias, no el contenido de dos objetos.
Stephan
2
@Alex para aclarar, el operador == en Java es para verificar si dos objetos apuntan a la misma ubicación en la memoria, o si dos tipos primitivos (byte, short, int, long, float, double, char, boolean) son iguales.
La-comadreja
2
@Stephan, lo ==mencionado es solo JavaScript; nunca se menciona con respecto a Java.
Olathe
@anestv, hay diferencias ( ==en JavaScript es mucho más flexible que contentEquals, lo que no tocará números, por ejemplo), pero está en lo correcto al equalsverificar una coincidencia de tipo exacta conStrings (otras clases podrían ser más flexibles con los tipos en sus equalsmétodos) .
Olathe
43

Para decirlo fácilmente: String.contentEquals()es el hermano más inteligente de String.equals(), porque puede ser más libre en la implementación que String.equals().

Hay algunas razones por las cuales hay un String.contentEquals()método separado . La razón más importante que creo es:

  • El equalsmétodo tiene que ser reflexivo. Eso significa que: x.equals(y) == y.equals(x). Esto implica que aString.equals(aStringBuffer)tendría que ser lo mismo que aStringBuffer.equals(aString). Esto requeriría que los desarrolladores de la API Java realicen una implementación especial para Strings en el equals()método de StringBuffer, StringBuilder y CharSequence también. Esto sería un desastre.

Aquí es donde String.contentEqualsentra. Se trata de un método independiente que no no tiene por qué seguir los estrictos requisitos y normas para Object.equals. De esta manera, puede implementar el sentido de "contenido igual" más libremente. Esto le permite hacer comparaciones inteligentes entre un StringBuffer y un String, por ejemplo.

Y para decir cuál es exactamente la diferencia:

  • String.contentEquals()puede comparar los contenidos de a String, a StringBuilder, a StringBuffer, a CharSequencey todas las clases derivadas de estos. Si el parámetro es de tipo String, String.equals()se ejecuta.

  • String.equals()solo compara objetos String. Todos los demás tipos de objetos se consideran no iguales.

  • String.contentEquals()puede comparar StringBuffery StringBuilderde manera inteligente. No , no llame a la pesada toString()método, que copia todo el contenido de un nuevo objeto String. En cambio, se compara con la char[]matriz subyacente , que es genial.

Martijn Courteaux
fuente
31

Esta respuesta ya fue publicada por dbw, pero la eliminó, pero tenía algunos puntos muy válidos para la diferencia al comparar el tiempo de ejecución, qué excepciones se lanzan,

Si observa el código fuente String # equals y String # contentEquals , está claro que hay dos métodos anulados para String#contentEqualsuno que toma StringBuildery otro CharSequence.
La diferencia entre ellos

  1. String#contentEqualsarrojará NPE si el argumento proporcionado es nullpero String#equalsdevolveráfalse
  2. String#equalscompara el contenido solo cuando el argumento proporcionado es, de lo instance of Stringcontrario, volverá falseen todos los demás casos, pero por otro lado String#contentEqualsverifica el contenido de todos los objetos que implementan la interfaz CharSequence.
  3. También puede ajustar el código para que String#contentEqualsdevuelva el resultado incorrecto o el resultado que desea anulando el equalsmétodo del argumento pasado como se muestra a continuación, pero no puede hacer esos ajustes String#equals.
    El siguiente código siempre producirátrue siempre que scontenga cualquiera de 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á más lento que String#Equalscuando el argumento proporcionado es instance of Stringy la longitud de ambos Stringes la misma pero el contenido no es igual.
    Ejemplo si las cadenas son String s = "madam"y String argPassed = "madan"luego s.contentEquals(argPassed)tomarán casi el doble de tiempo de ejecución en este caso en comparación cons.equals(argPassed)

  5. Si la longitud del contenido no es la misma para ambas cadenas, la función String#contentEqualstendrá un mejor rendimiento que String#Equalsen casi todos los casos posibles.

Un punto más para agregar a su respuesta

  1. String#contentEqualsde un Stringobjeto también se comparará con el StringBuildercontenido y proporcionará el resultado apropiado, mientras String#Equalsque devolveráfalse
Prateek
fuente
44
@dbw esta respuesta es de la respuesta que publicaste
Prateek
@dbw Además, ¿por qué eliminaste tu publicación de todos modos?
MC Emperor
14
  • StringEl equals(Object o)método de clase solo hace Stringcomparación. Pero las contentEquals(CharSequence cs)comprobaciones para las clases se extienden , AbstractStringBuilderes decir StringBuffer, StringBuildery la Stringclase también (todas son de tipo CharSequence).

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

salida:

false
true

La salida del primero stmt es falseporque builderno es de tipo Stringde modo equals()rendimientos falsepero los contentEquals()controles para el contenido de todo el tipo como StringBuilder, StringBuffer, Stringy como el contenido es el mismo, por lo tanto true.

  • contentEqualslanzará NullPointerExceptionsi el argumento proporcionado es nullpero equals()devolverá falso porque equals () verifica por ejemplo Of ( if (anObject instance of String)) que devuelve falso si el argumento es null.
Molesto
fuente
14

contentEquals(CharSequence cs):

  • Permite comprobar la igualdad de valor de cadena dada con cualquier instancia de implementación de la interfaz java.lang.CharacterSequence(por ejemplo, CharBuffer, Segment, String, StringBuffer, StringBuilder)

equals(Object anObject):

  • Le permite verificar la igualdad del valor de cadena dado con cualquier instancia de tipo java.lang.String solamente

RTFC :)

Como leer la fuente es la mejor manera de entenderla, comparto las implementaciones de ambos métodos (a partir de 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;
 }

Hay otro método de String # contentEquals ():

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

equals()y contentEquals()son dos métodos en Stringclase para comparar dos stringsy stringcon StringBuffer.

Los parámetros de contentEquals()son StringBuffery String(charSequence). equals()se usa para comparar dos stringsy contentEquals()se usa para comparar el contenido de Stringy StringBuffer.

Método contentEqualsy equalsson

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

Aquí hay un código que describe ambos 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);
    }
}

Salida:

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

String # equals toma Object como argumento y comprueba si es una instancia de String object o no. Si el objeto de argumento es String Object, compara el contenido carácter por carácter. Devuelve verdadero en caso de que el contenido de ambos objetos de cadena sea el mismo.

La cadena # contentEquals toma la interfaz CharSequence como argumento. CharSequence se puede implementar de 2 maneras: usando i) la clase String o (ii) AbstractStringBuilder (clase padre de StringBuffer, StringBuilder)

En contentEquals () la longitud se compara antes de cualquier comprobación de instancia de objeto. Si la longitud es la misma, comprueba si el objeto argumento es una instancia de AbstractStringBuilder o no. Si es así (es decir, StringBuffer o StringBuilder), el contenido se verifica carácter por carácter. En caso de que el argumento sea una instancia del objeto String, String # es igual a llamado desde String # contentEquals.

En resumen,

Cadena # igual compara el contenido carácter por carácter en caso de que el argumento sea también un objeto Cadena. Y String # contentEquals compara el contenido en caso de que el objeto de argumento implemente la interfaz CharSequence.

String # contentEquals es más lento en caso de que comparemos dos contenidos de cadena de la misma longitud que String # contentEquals internamente llama a String # igual para el objeto String.

En caso de que intentemos comparar objetos con diferente longitud de contenido (digamos "abc" con "abcd"), String # contentEquals es más rápido que String # igual. Porque la longitud se compara antes de cualquier comprobación de instancia de objeto.

Anirban Pal
fuente
6

Los contentEquals()cheques método es el contenido son los mismos entre una String, StringBuffer, etc, que algún tipo de secuencia de carbón.

fastcodejava
fuente
5

Por cierto, la razón histórica de la diferencia es que String originalmente no tenía superclase, por lo que String.equals () toma un String como argumento. Cuando se introdujo CharSequence como la superclase de String, necesitaba una prueba de igualdad propia que funcionara en todas las implementaciones de CharSequence, y que no colisionaría con los equals () ya en uso por String ... así que obtuvimos CharSequence.contentEquals ( ), que es heredado por String.

Si CharSequence ha estado presente en Java 1.0, probablemente solo tendríamos CharSequence.equals () y String simplemente implementaría eso.

Ah, las alegrías de los lenguajes en evolución ...

keshlam
fuente