Java строк: метод compareto() и равна()


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

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

19 106

19 ответов:

разница в том, что "foo".equals((String)null) возвращает false while "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. Строки-это один из классов который реализовал 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. equals(y) не является взаимозаменяемым с x.compareTo (y) == 0. Первый сравнивает идентичность, в то время как другой сравнивает понятие "размер". Это правда, что во многих случаях, особенно с примитивными типами, эти два совпадают.

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

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

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

Если x. compareTo(y) равно 0, это не обязательно означает, что x.equals (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 оператора 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, если объект не имеет того же типа, что и экземпляр.

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

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

"равно" сравнить объекты и вернуть true или false и "сравнить" вернуть 0, если это правда или количество [> 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 () проверяет, равны ли две строки или not.It дает логическое значение. compareTo () проверяет, равен ли объект string, больше или меньше другой строки object.It дает результат как : 1 Если строковый объект больше 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() over equals() что compareTo работает для классов, которые реализуют "сопоставимый" интерфейс в противном случае он будет бросать NullPointerException. String классы реализуют сопоставимый интерфейс в то время как StringBuffer не значит, что вы можете использовать "foo".compareTo("doo") на String объект, но не в