2009-10-11 70 views
96

Cuando se prueba la igualdad de String 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 en lugar de equals(). Esto se siente antinatural (como compareTo() está destinado a proporcionar un pedido 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í.Java Strings: compareTo() vs equals()

No sabía por qué le enseñaron a usar compareTo() en lugar de equals() para String, 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?

+9

Estrictamente hablando a un nivel micro-optimización, que nunca debemos hablar prematuramente a, '.equalsIgnoreCase()' es la comparación más rápido si es apropiado, de lo contrario '.equals()' es lo que quieres –

Respuesta

85

La 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.

+4

Creo que también deberías mencionar esto.Equals calcula el hashcode. El código hash de dos cadenas diferentes, aunque es raro, puede ser el mismo. Pero al usar compareTo(), comprueba las cadenas carácter por carácter. Entonces, en este caso, dos cadenas devolverán verdadero si y solo si sus contenidos reales son iguales. – Ashwin

+23

¿Por qué crees que equivale a calcular el hashcode? Puede ver que este no es el caso: http://www.docjar.com/html/api/java/lang/String.java.html (línea 1013). – waxwing

+2

tienes razón. Pensé que iguales y hashcode van de la mano (es igual a verifica si ambos tienen el mismo código hash). Entonces, ¿por qué es necesario anular estos dos métodos si decide anular cualquiera de ellos? – Ashwin

4

Parece que ambos métodos hacen más o menos lo mismo, pero el método compareTo() toma una Cadena, no un Objeto, y agrega alguna funcionalidad adicional 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 programador 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

20

Los 2 diferencias principales son que:

  1. equals se llevará a cualquier objeto como un parámetro, pero compareTo solamente tendrá Strings.
  2. equals solo dice si son iguales o no, pero compareTo brinda información sobre cómo las cadenas se comparan lexicográficamente.

Eché un vistazo a the String class code, y el algoritmo dentro de ComparaTo 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 cadenas y no cuál viene primero lexicográficamente, entonces usaría equals.

24

Al comparar por igualdad, debe usar equals(), ya que 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 se aplica en general, no solo para cadenas.

15

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

8

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

Pero compareTo() da el orden de los objetos, suele utilizarse en la clasificación de objetos en orden ascendente o mientras equals() sólo se hablará de la igualdad y decir si son iguales o no descender.

1

String.equals() requiere la invocación de operador instanceof mientras compareTo() no requiere. Mi colega ha notado una gran lista desplegable de rendimiento causada por un número excesivo de instanceof llamadas en el método equals(), sin embargo, mi prueba ha demostrado compareTo() ser 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.

+1

Supongo que debe haber usado cadenas muy cortas, todas de la misma longitud y con alta diversidad en el primer carácter para obtener un resultado donde 'compareTo()' es más rápido que 'equals()'? Pero para la mayoría de los conjuntos de datos del mundo real, 'equals()' es mucho más rápido que 'compareTo() == 0'. 'equals()' brilla si las cadenas tienen un prefijo común pero diferentes longitudes o si en realidad son el mismo objeto. – x4u

+0

Bueno, mi prueba fue contra hipotesis que instanceof es el asesino de rendimiento, por lo que las cuerdas fueron cortas de hecho. –

+0

Si la cadena es aleatoria y la mayoría difiere en longitud, la opción más obvia debería ser el método equals() sobre compareTo() ya que en la mayoría de los casos devolverá falso de manera inmediata si no tienen la misma longitud. – sactiw

2

Hay ciertas cosas que debe tener en cuenta al anular compareTo en Java, p. Compareto debe ser consistente con iguales y la resta no se debe usar para comparar campos enteros ya que pueden desbordarse. check Things to remember while overriding Comparator in Java para más detalles.

1
  1. equals puede tomar cualquier objeto como un parámetro, pero sólo puede tener compareTo cadena.

  2. cuando nula COMETO, compareTo arrojará una excepción

  3. cuando se quiere saber dónde está el diff suceda, puede utilizar compareTo.

+0

compareTo puede tomar cualquier objeto como argumento. Como @apurva jadhav dijo anteriormente, comparable toma un argumento genérico. Si implementa comaparable como Comparable , entonces puede usar solo cadenas. –

8

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

comparePara 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 
5

equals() debe ser el método de elección en el caso de la OP.

En cuanto a la implementación de equals() y compareTo() en java.lang.String on grepcode, podemos ver fácilmente que es igual es mejor si sólo estamos interesados ​​en la igualdad de las dos cadenas:

equals():

1012 publicboolean equals(Object anObject) {
1013 if (this == anObject) {
1014 returntrue;
1015 }
1016 if (anObject instanceofString) {
1017 String anotherString = (String)anObject;
1018 int n = count;
1019 if (n == anotherString.count) {
1020 char v1[] = value;
1021 char v2[] = anotherString.value;
1022 int i = offset;
1023 int j = anotherString.offset;
1024 while (n-- != 0) {
1025 if (v1[i++] != v2[j++])
1026 returnfalse;
1027 }
1028 returntrue;
1029 }
1030 }
1031 returnfalse;
1032 }

y compareTo() :

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

Cuando uno de la cadena s es un prefijo de otro, el rendimiento de compareTo() es peor, ya que aún necesita determinar el orden lexicográfico, mientras que equals() ya no se preocupe más y devuelve falso inmediatamente.

En mi opinión, debemos utilizar estos dos ya que estaban destinados:

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

Este es un experimento en la nigromancia :-)

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

Su 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 la siguiente:

Si X e Y son idénticos, comparten el mismo 'tamaño': si x.equals (y) es cierto => 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. Así que 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.

+1

x.equals (y) no significa Identidad, significa Igualdad. La identidad se compara utilizando x == y para tipos definidos por el usuario en Java. –

0

Igual -

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

2- No arroje 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. 

invocaciones sucesivas de x.equals (y) devuelven el mismo valor, siempre que el objeto referenciado por X e Y no son modificados.

x.Equals(null) returns false. 

4- Para algunos tipos de objetos, es deseable tener Igual a prueba de igualdad de valor 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)); 

de salida: -

False 
True 

mientras compareTo -

compara la instancia actual con otro objeto del mismo tipo y devuelve un 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 ject.

Devuelve -

Menos que cero - Esta instancia precede 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, puede visitar aquí.

Así que sugiero que sea mejor usar Equals en lugar de compareTo.

+0

No hay método 'GetHashCode()'. ¿Te refieres a 'hashCode()'? – EJP

1
  • equals: necesarios para comprobar la igualdad y la restricción de los duplicados. Muchas clases de biblioteca de Java usan esto en caso de que quieran encontrar duplicados. p.ej. HashSet.add(ob1) solo se agregará si eso no existe. Entonces, si está extendiendo algunas clases como esta, entonces anule equals().

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

0

"es igual a" comparar objetos y devolver verdadero o falso y "comparar" devolver 0 si es verdad o un número [> 0] o [< 0] si es falsa aquí un ejemplo:

<!-- language: lang-java --> 
//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

Documentation Equals: https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object)

2

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é hashCode, podría ser incluso más rápido rechazar a los no iguales en caso de que el código hash no coincida.

4

iguales() pueden ser más eficientes a continuación compareTo().

Una diferencia muy importante entre compareTo y es igual a:

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

equals() comprueba si dos objetos son los mismos 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 compareTo() hace.

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

0

equals() comprueba si dos cadenas son iguales o no. Proporciona un valor booleano. compareTo() comprueba si el objeto de cadena es igual, mayor o menor que el otro objeto de cadena. Da como resultado: 1 si el objeto de cadena es mayor 0 si ambos son iguales -1 si la cadena es más pequeña 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