Строки Java: compareTo () против equals()

при тестировании на равенство Stringв Java я всегда использовал equals() потому что мне кажется, что это самый естественный метод для него. В конце концов, его название уже говорит о том, что он намерен делать. Тем не менее, мой коллега недавно сказал мне, что меня научили использовать compareTo() == 0 вместо equals(). Это кажется неестественным (as compareTo() предназначен для обеспечения порядка и не сравнить для равенства) и даже несколько опасно (потому что compareTo() == 0 не обязательно подразумевает равенство во всем случаи, хотя я знаю, что это делает для String ' s) ко мне.

он не знал, почему его учили пользоваться compareTo() вместо equals() на String, и я также не мог найти никакой причины, почему. Это действительно вопрос личного вкуса, или есть какая-то реальная причина для любого метода?

19 ответов


разница в том, что "foo".equals((String)null) возвращает false, в то время как "foo".compareTo((String)null) == 0 создает исключение NullPointerException. Поэтому они не всегда взаимозаменяемы даже для струн.


при сравнении на равенство, вы должны использовать equals(), потому что он ясно выражает ваше намерение.

compareTo() имеет дополнительный недостаток, что он работает только на объекты, которые реализуют Comparable интерфейс.

это относится в целом, а не только к строкам.


2 основных отличия в том, что:

  1. equals возьмем любой объект в качестве параметра, но compareTo займет строк.
  2. equals только говорит вам, равны они или нет, но compareTo дает информацию о том, как строки сравниваются лексикографически.

Я взглянул на код класса String, и алгоритм в compareTo и equals выглядит в основном одинаково. Я считаю, что его мнение было просто вопросом о вкусе, и я согласен с вами-если все, что вам нужно знать, это равенство строк, а не то, какая из них лексикографически первая, тогда я бы использовал equals.


compareTo и делать больше работы, если строки имеют разную длину. equals может просто вернуть false, в то время как compareTo необходимо всегда проверять достаточное количество символов, чтобы найти порядок сортировки.


В Контексте Строки:
compareTo: сравнивает две строки лексикографически.
равна: сравнивает эту строку с указанным объектом.

compareTo сравнивает две строки по их символам (с тем же индексом) и возвращает целое число (положительное или отрицательное) соответственно.

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() применяется не только к строкам, но и к любому другому объекту, потому что compareTo<T> принимает общий аргумент T. String является одним из классов, который реализовал compareTo() способ реализации Comparable интерфейс.(compareTo () - это метод для сопоставимого интерфейса). таким образом, любой класс может реализовать сопоставимый интерфейс.

но compareTo() дает порядок объектов, обычно используется при сортировке объектов по возрастанию или порядок убывания пока equals() будем говорить только о равенстве и скажите, равны они или нет.


равна() может быть более эффективным, то compareTo ().

очень важное различие между compareTo и equals:

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

равна() проверяет, совпадают ли два объекта или нет, и возвращает логическое значение.

compareTo () (из интерфейса Comparable) возвращает целое число. Он проверяет, какой из двух объектов "меньше", "равен" или "больше" другого. Не все объекты могут быть логически упорядочены, поэтому метод compareTo () не всегда имеет смысл.

обратите внимание, что equals() не определяет порядок между объектами, который compareTo () делает.

теперь я советую вам просмотреть исходный код обоих методов, чтобы сделать вывод, что equals предпочтительнее compareTo, который включает в себя некоторые математические вычисления.


похоже, что оба метода в значительной степени делают то же самое, но метод compareTo() принимает строку, а не объект, и добавляет некоторые дополнительные функции поверх обычного метода equals (). Если все, что вас волнует, это равенство, то метод equals() является лучшим выбором, просто потому, что он имеет больше смысла для следующего программиста, который смотрит на ваш код. Разница во времени между двумя различными функциями не должна иметь значения, если вы не зацикливаетесь на каком-то огромном количестве предметы. CompareTo () действительно полезен, когда вам нужно знать порядок строк в коллекции или когда вам нужно знать разницу в длине между строками, которые начинаются с той же последовательности символов.

источник:http://java.sun.com/javase/6/docs/api/java/lang/String.html


equals() должен быть методом выбора в случае OP.

глядя на реализацию equals() и compareTo() на java.ленг.Строка на grepcode, мы можем легко видеть, что equals лучше, если мы просто обеспокоены равенством двух строк:

equals():

1012  public boolean equals(Object anObject) {
1013 if (this == anObject) {
1014 return true;
1015 }
1016 if (anObject instanceof String) {
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 return false;
1027 }
1028 return true;
1029 }
1030 }
1031 return false;
1032 }

и compareTo():

1174  public int 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 }

когда одна из строк является префиксом другого, результативность compareTo() хуже, как это еще необходимо определить лексикографический порядок в то время как equals() больше не будет беспокоиться и немедленно вернет false.

на мой взгляд, мы должны использовать эти два, как они были задуманы:

  • equals() проверить на равенство, и
  • compareTo() чтобы найти лексический порядок.

есть определенные вещи, которые вам нужно иметь в виду при переопределении compareTo в Java, например, Compareto должен быть согласован с equals и вычитание не должно использоваться для сравнения целочисленных полей, поскольку они могут переполняться. проверка вещи, которые нужно помнить при переопределении компаратора в Java для сведения.


Equals может быть более эффективным, чем compareTo.

Если длина последовательностей символов в строке не совпадает, строки не могут быть равны, поэтому отклонение может быть намного быстрее.

кроме того, если это тот же объект (равенство личности, а не логическое равенство), он также будет более эффективным.

Если они также реализовали кэширование хэш-кода, может быть еще быстрее отклонить неравные в случае, если их хэш-код не совпадает.


  1. equals можно взять любой объект в качестве параметра, но compareTo может принимать только строку.

  2. когда cometo null,compareTo выдаст исключение

  3. когда вы хотите знать, где происходит разница, вы можете использовать compareTo.


это эксперимент по некромантии: -)

большинство ответов сравнивают производительность и различия API. Они упускают фундаментальный момент, что эти две операции просто имеют различную семантику.

ваша интуиция верна. х.равна(г) не взаимозаменяемы с X.метод compareto(г) == 0. Первый сравнивает идентичность, в то время как другой сравнивает понятие "размер". Это правда, что во многих случаях, особенно с примитивными типами, эти два совпадают.

в общий случай таков:

Если x и y идентичны, они имеют одинаковый "размер": если x.равно (y) равно true => x.compareTo (y) равно 0.

однако, если x и y имеют одинаковый размер, это не означает, что они идентичны.

Если x.compareTo (y) равно 0 не обязательно означает x.равно (y) истинно.

убедительным примером, где идентичность отличается от размера, будут комплексные числа. Предположим, что сравнение производится по их абсолютной величине. Итак, дано два комплексные числа: Z1 = a1 + b1 * i и Z2 = a2 + b2 * i:

Z1.equals (z2) возвращает true тогда и только тогда, когда a1 = a2 и b1 = b2.

Однако Z1.compareTo (Z2) возвращает 0 для бесконечного числа пар (a1,b1) и (a2,b2), если они удовлетворяют условию a1^2 + b1^2 == a2^2 + b2^2.


  • equals: требуется для проверки равенства и ограничения дубликатов. Многие классы библиотеки Java используют это в случае, если они хотят найти дубликаты. например,HashSet.add(ob1) добавит только если этого не существует. Поэтому, если вы расширяете некоторые классы, подобные этому, переопределите equals().

  • compareTo: требуется для заказа элемента. Опять же для стабильной сортировки вам требуется равенство, поэтому есть возврат 0.


String.equals() требует вызова instanceof оператор while compareTo() требует не. Мой коллега отметил большое падение производительности, вызванное чрезмерным количеством instanceof звонки equals() метод, однако мой тест оказался compareTo() чтобы быть только немного быстрее.

я использовал, однако, Java 1.6. В других версиях (или других поставщиках JDK) разница может быть больше.

тест сравнивал каждую строку в 1000 элементах массивы, повторяется 10 раз.


равна -

1 - переопределите метод GetHashCode, чтобы тип работал правильно в хэш-таблице.

2 - Не создавайте исключение при реализации метода Equals. Вместо этого верните false для аргумента null.

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.

последовательные вызовы X. Equals (y) возвращает то же значение, пока объект, на который ссылаются x и y, не изменяется.

x.Equals(null) returns false.

4 - Для некоторых видов объектов желательно иметь тест Equals для равенства значений вместо ссылочного равенства. Такие реализации Equals возвращает true, если два объекта имеют одинаковое значение, даже если они не в одном экземпляре.

Например

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

выход :-

False
True

пока compareTo -

сравнивает текущий экземпляр с другим объектом того же типа и возвращает целое число, которое показывает, расположен ли текущий экземпляр перед, после или на той же позиции в порядке сортировки, что и другой объект.

возвращает -

меньше нуля-этот экземпляр предшествует obj в порядке сортировки. Ноль-этот экземпляр находится в той же позиции в порядке сортировки, что и obj. Больше нуля-этот экземпляр следует за obj в порядке сортировки.

Он может вызвать исключение ArgumentException, если объект не является тем же типом, что и экземпляр.

например, вы можете посетить здесь.

Так Что Я предложите лучше использовать Equals вместо compareTo.


"equals" сравнивает объекты и возвращает true или false и "сравнить с" возвращает 0, если true или число [> 0] или [

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

результаты:

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

документация сравните с:https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html

Документация Равна : https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object)


equals () проверяет, равны ли две строки или нет.Это дает логическое значение. compareTo () проверяет,равен ли объект string другому объекту string, больше или меньше.Это дает результат как : 1 если объект string больше 0, если оба равны -1 если строка меньше другой строки

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

здесь одна вещь важна при использовании compareTo() над equals() что compareTo работает для классов, которые реализуют "сопоставимый" интерфейс, иначе он будет бросать NullPointerException. String классов реализует comparable интерфейс, а StringBuffer не значит, что вы можете использовать "foo".compareTo("doo") на String объект, но не в