Cadenas de Java: compare a () frente a igual ()

Al probar la igualdad de String ‘s en Java, siempre he usado equals() porque para mí este parece ser el método más natural para ello. Después de todo, su nombre ya dice lo que está destinado a hacer. Sin embargo, un colega mío me dijo recientemente que se le había enseñado a usar compareTo() == 0 lugar de equals() . Esto se siente antinatural (como compareTo() pretende proporcionar un orden y no comparar para la igualdad) e incluso algo peligroso (porque compareTo() == 0 no implica necesariamente la igualdad en todos los casos, aunque sé que lo hace para String ‘ s) para mí.

No sabía por qué le enseñaron a usar compareTo() lugar de equals() para String ‘s, y tampoco pude encontrar ningún motivo. ¿Es realmente una cuestión de gusto personal, o hay alguna razón real para cualquiera de los métodos?

Una diferencia es que "foo".equals((String)null) devuelve falso mientras que "foo".compareTo((String)null) == 0 arroja una NullPointerException. Por lo tanto, no siempre son intercambiables incluso para Strings.

Al comparar por igualdad, debe usar equals() , porque expresa su intención de una manera clara.

compareTo() tiene el inconveniente adicional de que solo funciona en objetos que implementan la interfaz Comparable .

Esto aplica en general, no solo para cadenas.

Las 2 diferencias principales son que:

  1. equals tomará cualquier Object como parámetro, pero compareTo solo tomará Strings.
  2. equals solo te dice si son iguales o no, pero compareTo proporciona información sobre cómo las cadenas se comparan lexicográficamente.

Eché un vistazo al código de clase String , y el algoritmo dentro de compareTo e iguales parece básicamente el mismo. Creo que su opinión fue solo una cuestión de gusto, y estoy de acuerdo con usted: si todo lo que necesita saber es la igualdad de las cuerdas y no cuál viene primero lexicográficamente, entonces usaría equals .

compareTo tiene que hacer más trabajo si las cadenas tienen diferentes longitudes. equals puede simplemente devolver false, mientras que compareTo siempre debe examinar suficientes caracteres para encontrar el orden de clasificación.

En contexto de cadena:
compareTo: Compara dos cadenas lexicográficamente.
equals: Compara esta cadena con el objeto especificado.

compararPara comparar dos cadenas por sus caracteres (en el mismo índice) y devuelve un número entero (positivo o negativo) en consecuencia.

 String s1 = "ab"; String s2 = "ab"; String s3 = "qb"; s1.compareTo(s2); // is 0 s1.compareTo(s3); // is -16 s3.compareTo(s1); // is 16 

compareTo() no solo se aplica a cadenas sino también a cualquier otro objeto porque compareTo toma un argumento genérico T String es una de las clases que ha implementado el compareTo() implementando la interfaz Comparable . (compareTo () es un método para la interfaz comparable). Entonces cualquier clase es libre de implementar la interfaz Comparable.

Pero compareTo() proporciona el orden de los objetos , que se usa normalmente para clasificar objetos en orden ascendente o descendente, mientras que equals() solo hablará sobre la igualdad y dirá si son iguales o no.

equals () puede ser más eficiente que compareTo () .

Una diferencia muy importante entre compareTo y equals:

 "myString".compareTo(null); //Throws java.lang.NullPointerException "myString".equals(null); //Returns false 

equals () comprueba si dos objetos son iguales o no y devuelve un valor booleano.

compareTo () (de la interfaz Comparable) devuelve un número entero. Comprueba cuál de los dos objetos es “menor que”, “igual a” o “mayor que” el otro. No todos los objetos pueden ordenarse lógicamente, por lo que un método compareTo () no siempre tiene sentido.

Tenga en cuenta que equals () no define el orden entre los objetos, que comparaTo () hace.

Ahora te aconsejo que revises el código fuente de ambos métodos para concluir que es preferible que comparar, lo que implica algunos cálculos matemáticos.

Parece que ambos métodos hacen prácticamente lo mismo, pero el método compareTo () toma una Cadena, no un Objeto, y agrega alguna funcionalidad extra sobre el método Equals () normal. Si lo único que te importa es la igualdad, entonces el método equals () es la mejor opción, simplemente porque tiene más sentido para el próximo progtwigdor que eche un vistazo a tu código. La diferencia de tiempo entre las dos funciones diferentes no debería importar a menos que esté pasando por encima de una gran cantidad de elementos. El compareTo () es realmente útil cuando necesita conocer el orden de Strings en una colección o cuando necesita conocer la diferencia de longitud entre cadenas que comienzan con la misma secuencia de caracteres.

fuente: http://java.sun.com/javase/6/docs/api/java/lang/String.html

equals() debería ser el método de elección en el caso del OP.

Si observamos la implementación de equals() y compareTo() en java.lang.String en grepcode , podemos ver fácilmente que igual es mejor si solo nos preocupa la igualdad de dos cadenas:

equals() :

  1012 public boolean equals ( Object anObject) { 
1013 if ( this == unObjeto) {
1014 devuelve verdadero ;
1015 }
1016 if (anObject instanceof String ) {
1017 String anotherString = ( String ) anObject;
1018 int n = conteo;
1019 if (n == anotherString.count) {
1020 char v1 [] = valor;
1021 char v2 [] = anotherString.value;
1022 int i = desplazamiento;
1023 int j = anotherString.offset;
1024 mientras (n--! = 0) {
1025 si (v1 [i ++]! = V2 [j ++])
1026 devuelve falso ;
1027 }
1028 devuelve verdadero ;
1029 }
1030 }
1031 devuelve falso ;
1032 }

y compareTo() :

  1174 public int compareTo ( String anotherString) { 
1175 int len1 = count;
1176 int len2 = anotherString.count;
1177 int n = Matemáticas. min (len1, len2);
1178 char v1 [] = valor;
1179 char v2 [] = anotherString.value;
1180 int i = desplazamiento;
1181 int j = anotherString.offset;
1183 si (i == j) {
1184 int k = i;
1185 int lim = n + i;
1186 mientras (k 1187 char c1 = v1 [k];
1188 char c2 = v2 [k];
1189 si (c1! = C2) {
1190 return c1 - c2;
1191 }
1192 k ++;
1193 }
1194 } else {
1195 mientras (n--! = 0) {
1196 char c1 = v1 [i ++];
1197 char c2 = v2 [j ++];
1198 si (c1! = C2) {
1199 return c1 - c2;
1200 }
1201 }
1202 }
1203 return len1 - len2;
1204 }

Cuando una de las cadenas es un prefijo de otra, el rendimiento de compareTo() es peor ya que aún necesita determinar el orden lexicográfico mientras que equals() ya no se preocupará y devolverá false inmediatamente.

En mi opinión, deberíamos usar estos dos como estaban destinados:

  • equals() para verificar la igualdad, y
  • compareTo() para encontrar el orden léxico.

Hay ciertas cosas que debe tener en cuenta al anular compareTo en Java, por ejemplo, Compareto debe ser coherente con los iguales y la resta no se debe utilizar para comparar campos enteros, ya que pueden desbordarse. Verifique las cosas que debe recordar al anular el comparador en Java para obtener más detalles.

Iguales pueden ser más eficientes que compare.

Si la longitud de las secuencias de caracteres en String no coincide, no hay manera de que las cadenas sean iguales, por lo que el rechazo puede ser mucho más rápido.

Además, si es el mismo objeto (igualdad de identidad en lugar de igualdad lógica), también será más eficiente.

Si también implementaron el almacenamiento en caché de hashCode, podría ser aún más rápido rechazar a los no iguales en caso de que no coincida con el código hash.

  1. equals puede tomar cualquier Object como parámetro pero compareTo solo puede tomar String.

  2. cuando sea nulo, compareTo lanzará una excepción

  3. cuando desee saber dónde ocurre la diferencia, puede usar compareTo .

Este es un experimento de nigromancia 🙂

La mayoría de las respuestas comparan las diferencias de rendimiento y API. Extrañan el punto fundamental de que las dos operaciones simplemente tienen una semántica diferente.

Tu intuición es correcta. x.equals (y) no es intercambiable con x.compareTo (y) == 0. El primero compara la identidad, mientras que el otro compara la noción de ‘tamaño’. Es cierto que en muchos casos, especialmente con los tipos primitivos, estos dos co-alinean.

El caso general es este:

Si xey son idénticos, comparten el mismo ‘tamaño’: si x.equals (y) es verdadero => x.compareTo (y) es 0.

Sin embargo, si xey comparten el mismo tamaño, no significa que sean idénticos.

si x.compareTo (y) es 0 no necesariamente significa que x.equals (y) es verdadero.

Un ejemplo convincente en el que la identidad difiere del tamaño serían los números complejos. Supongamos que la comparación se realiza por su valor absoluto. Entonces, dados dos números complejos: Z1 = a1 + b1 * i y Z2 = a2 + b2 * i:

Z1.equals (z2) devuelve verdadero si y solo si a1 = a2 y b1 = b2.

Sin embargo, Z1.compareTo (Z2) devuelve 0 para un número infinito de pares (a1, b1) y (a2, b2) siempre que satisfagan la condición a1 ^ 2 + b1 ^ 2 == a2 ^ 2 + b2 ^ 2.

  • equals : requerido para verificar la igualdad y restringir duplicados. Muchas clases de biblioteca de Java usan esto en caso de que quieran encontrar duplicados. por ejemplo, HashSet.add(ob1) solo se agregará si eso no existe. Entonces, si está extendiendo algunas clases como esta, anule equals() .

  • compareTo : requerido para ordenar el elemento. De nuevo para la clasificación estable, usted requiere igualdad, por lo que hay un retorno 0.

String.equals() requiere invocar el operador instanceof mientras que compareTo() no requiere. Mi colega ha observado una gran lista desplegable de rendimiento causada por un número excesivo de llamadas de instanceof en el método equals() , sin embargo, mi prueba ha demostrado que compareTo() es solo un poco más rápida.

Estaba usando, sin embargo, Java 1.6. En otras versiones (u otros proveedores de JDK), la diferencia podría ser mayor.

La prueba comparó cada cadena de cada una en matrices de 1000 elementos, repetidas 10 veces.

Igual –

1- Anule el método GetHashCode para permitir que un tipo funcione correctamente en una tabla hash.

2- No lanzar una excepción en la implementación de un método Equals. En cambio, devuelve falso para un argumento nulo.

3-

  x.Equals(x) returns true. x.Equals(y) returns the same value as y.Equals(x). (x.Equals(y) && y.Equals(z)) returns true if and only if x.Equals(z) returns true. 

Las invocaciones sucesivas de x.Equals (y) devuelven el mismo valor siempre que el objeto al que hacen referencia xey no se modifique.

 x.Equals(null) returns false. 

4- Para algunos tipos de objetos, es deseable tener la prueba Igual para la igualdad de valores en lugar de la igualdad referencial. Tales implementaciones de Equals devuelven verdadero si los dos objetos tienen el mismo valor, incluso si no son la misma instancia.

Por ejemplo –

  Object obj1 = new Object(); Object obj2 = new Object(); Console.WriteLine(obj1.Equals(obj2)); obj1 = obj2; Console.WriteLine(obj1.Equals(obj2)); 

Salida: –

 False True 

mientras que compareTo –

Compara la instancia actual con otro objeto del mismo tipo y devuelve un número entero que indica si la instancia actual precede, sigue o se produce en la misma posición en el orden de clasificación que el otro objeto.

Vuelve –

Menos que cero: esta instancia precede a obj en el orden de clasificación. Cero: esta instancia ocurre en la misma posición en el orden de clasificación que obj. Mayor que cero: esta instancia sigue a obj en el orden de clasificación.

Puede lanzar ArgumentException si el objeto no es del mismo tipo que la instancia.

Por ejemplo, puedes visitar aquí.

Así que sugiero usar Equals en lugar de compareTo.

“igual” compara objetos y devuelve verdadero o falso y “compara con” devuelve 0 si es verdadero o un número [> 0] o [<0] si es falso aquí un ejemplo:

  //Objects Integer Integer num1 = 1; Integer num2 = 1; //equal System.out.println(num1.equals(num2)); System.out.println(num1.compareTo(num2)); //New Value num2 = 3;//set value //diferent System.out.println(num1.equals(num2)); System.out.println(num1.compareTo(num2)); 

Resultados:

 num1.equals(num2) =true num1.compareTo(num2) =0 num1.equals(num2) =false num1.compareTo(num2) =-1 

Documentación Compare con: https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html

La documentación es igual a: https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object)

equals () comprueba si dos cadenas son iguales o no. Proporciona un valor booleano. compareTo () comprueba si el objeto string es igual a, mayor o menor que el otro objeto string. Da resultado como: 1 si el objeto string es mayor 0 si ambos son iguales -1 si string es más pequeño que otra cadena

eq:

 String a = "Amit"; String b = "Sumit"; String c = new String("Amit"); System.out.println(a.equals(c));//true System.out.println(a.compareTo(c)); //0 System.out.println(a.compareTo(b)); //1 

Aquí, una cosa es importante al usar compareTo() sobre equals() que compareTo funciona para las clases que implementan la interfaz ‘Comparable’, de lo contrario arrojará una NullPointerException . String clases de String implementan una interfaz comparable mientras que StringBuffer no puede usar "foo".compareTo("doo") en String objeto String pero no en el objeto StringBuffer .