125

在 Java中测试 's 的相等性时,String我一直使用它equals(),因为对我来说这似乎是最自然的方法。毕竟,它的名字已经说明了它打算做什么。但是,我的一位同事最近告诉我,有人教我使用compareTo() == 0而不是equals(). 这对我来说感觉不自然(因为compareTo()它是为了提供排序而不是比较相等),甚至有点危险(因为compareTo() == 0不一定在所有情况下都意味着相等,即使我知道它确实适用于String's)。

他不知道为什么教他使用compareTo()而不是equals()for String,我也找不到任何原因。这真的是个人品味问题,还是任何一种方法都有真正的理由?

4

21 回答 21

112

不同之处在于在抛出 NullPointerException"foo".equals((String)null)时返回 false 。"foo".compareTo((String)null) == 0因此,即使对于字符串,它们也不总是可以互换的。

于 2009-10-11T18:14:31.047 回答
37

两个主要区别是:

  1. equals将采用任何对象作为参数,但compareTo只会采用字符串。
  2. equals仅告诉您它们是否相等,但compareTo提供有关字符串如何按字典顺序比较的信息。

看了一下String类的代码,compareTo和equals里面的算法看起来基本一样。我相信他的意见只是一个口味问题,我同意你的看法——如果你只需要知道字符串的相等性而不是字典顺序上哪个先出现,那么我会使用equals.

于 2009-10-11T17:45:16.660 回答
29

在比较相等性时,您应该使用equals(),因为它以清晰的方式表达了您的意图。

compareTo()有一个额外的缺点,它只适用于实现Comparable接口的对象。

这通常适用,不仅适用于字符串。

于 2009-10-11T18:12:57.117 回答
20

compareTo如果字符串有不同的长度,它会做更多的工作。equals只能返回 false,而compareTo必须始终检查足够多的字符以找到排序顺序。

于 2009-10-11T18:28:23.610 回答
11

在字符串上下文中:
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
于 2012-07-07T06:58:57.150 回答
10

compareTo()不仅适用于字符串,还适用于任何其他对象,因为compareTo<T>它采用通用参数T。String 是compareTo()通过实现Comparable接口实现方法的类之一。(compareTo() 是可比较接口的方法)。所以任何类都可以自由地实现 Comparable 接口。

但是compareTo()给出对象的排序,通常用于按升序或降序对对象进行排序,而equals()只会谈论相等并说明它们是否相等。

于 2010-08-05T05:36:41.053 回答
7

equals()可以比compareTo()更有效。

compareTo 和 equals 之间的一个非常重要的区别:

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

equals()检查两个对象是否相同并返回一个布尔值。

compareTo()(来自接口 Comparable)返回一个整数。它检查两个对象中的哪个“小于”、“等于”或“大于”另一个。并非所有对象都可以按逻辑排序,因此 compareTo() 方法并不总是有意义。

请注意,equals() 没有定义对象之间的顺序,而 compareTo() 可以。

现在我建议您查看这两种方法的源代码,以得出 equals 优于涉及一些数学计算的 compareTo 的结论。

于 2016-05-28T08:58:13.680 回答
6

看起来这两种方法几乎都做同样的事情,但是 compareTo() 方法接受一个字符串,而不是一个对象,并在普通的 equals() 方法之上添加了一些额外的功能。如果你只关心相等,那么 equals() 方法是最好的选择,因为它对下一个查看你的代码的程序员来说更有意义。除非您循环处理大量项目,否则两个不同函数之间的时间差应该无关紧要。当您需要知道集合中字符串的顺序或需要知道以相同字符序列开头的字符串之间的长度差异时,compareTo() 非常有用。

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

于 2009-10-11T17:44:53.430 回答
5

equals()在 OP 的情况下应该是选择的方法。

查看grepcode 上 java.lang.String 中andequals()的实现,我们可以很容易地看到,如果我们只关心两个字符串的相等性,equals 会更好:compareTo()

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
1019 if (n == anotherString.count) {
1020 char v1[] = value; 第
1021
1022 整数i = 偏移量;第
1023
1024 (n-- != 0) {
1025 如果(v1[i++] != v2[j++])
1026 返回 false ;
1027 }
1028 返回
1029 }
1030 }
1031 返回
第1032

compareTo()

1174   public  int compareTo(String anotherString){ 
1175 int len1 = count; 第
1176
1177 分钟(len1, len2); 第
1178
1179
1180
1181
1183 1184
11851186


1187
1188
1189 章第1190
1191 } 1192 k++; 1193 } 1194 }其他{ 1195(n-- != 0) { 1196字符c1 = v1[i++]; 第1197第1198章如果(c1!= c2){ 1199返回c1-c2;1200 } 1201 } 1202 }












1203 返回len1 - len2;
第1204

当其中一个字符串是另一个字符串的前缀时,性能compareTo()更差,因为它仍然需要确定字典顺序,而equals()不再担心并立即返回 false。

在我看来,我们应该按预期使用这两个:

  • equals()检查是否相等,以及
  • compareTo()找到词法顺序。
于 2013-05-15T07:55:31.597 回答
3

equals() 检查两个字符串是否相等。它给出布尔值。compareTo() 检查字符串对象是否等于、大于或小于另一个字符串对象。它给出的结果为: 1 如果字符串对象大于 0 如果两者相等 -1 如果字符串小于其他字符串

情商:

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
于 2017-09-24T18:29:32.990 回答
2

String.equals()需要调用instanceof运算符,而不compareTo()需要。instanceof我的同事注意到方法中调用过多会导致性能大幅下降equals(),但我的测试证明compareTo()只是稍微快一点。

但是,我使用的是 Java 1.6。在其他版本(或其他 JDK 供应商)上,差异可能更大。

该测试比较了 1000 个元素数组中的每个字符串,重复 10 次。

于 2011-06-03T11:37:41.843 回答
2

在Java 中覆盖compareTo 时需要记住一些事项,例如Compareto 必须与equals 一致,并且不应该使用减法来比较整数字段,因为它们可能会溢出。检查在 Java 中覆盖 Comparator 时要记住的事情以获取详细信息。

于 2011-11-14T14:49:26.623 回答
2

这是一个死灵术实验:-)

大多数答案比较性能和 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) 当且仅当 a1 = a2 且 b1 = b2 时返回 true。

但是,只要满足条件 a1^2 + b1^2 == a2^2 + b2^2,Z1.compareTo(Z2) 就会为无限数量的 (a1,b1) 和 (a2,b2) 对返回 0。

于 2013-11-15T07:32:00.233 回答
2

Equals 比 compareTo 更有效。

如果字符串中字符序列的长度不匹配,则字符串不可能相等,因此拒绝会快得多。

此外,如果它是同一个对象(身份相等而不是逻辑相等),它也会更有效。

如果他们还实现了 hashCode 缓存,那么在他们的 hashCode 不匹配的情况下拒绝不等可能会更快。

于 2015-09-29T18:06:27.990 回答
1
  1. equals可以接受任何 Object 作为参数,但compareTo只能接受 String。

  2. cometo null 时,compareTo会抛出异常

  3. 当你想知道差异发生在哪里时,你可以使用compareTo.

于 2012-02-02T02:19:11.277 回答
1
  • equals:检查相等性和限制重复项所必需的。许多 Java 库类都使用它以防万一他们想查找重复项。egHashSet.add(ob1)只会在不存在的情况下添加。因此,如果您要扩展一些这样的类,请覆盖equals().

  • compareTo:元素排序所必需的。同样对于稳定排序,您需要相等,因此返回 0。

于 2014-07-05T10:09:37.263 回答
0

等于 -

1- 覆盖 GetHashCode 方法以允许类型在哈希表中正常工作。

2- 不要在 Equals 方法的实现中抛出异常。相反,为空参数返回 false。

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 和 y 引用的对象没有被修改,对 x.Equals(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

比较 -

将当前实例与另一个相同类型的对象进行比较,并返回一个整数,该整数指示当前实例在排序顺序中是在另一个对象之前、之后还是出现在相同位置。

它返回 -

小于零 - 此实例在排序顺序中位于 obj 之前。零 - 此实例在排序顺序中与 obj 出现在同一位置。大于零 - 此实例在排序顺序中位于 obj 之后。

如果对象与实例的类型不同,它可能会抛出 ArgumentException。

例如,您可以访问这里。

所以我建议最好使用 Equals 代替 compareTo。

于 2013-11-15T07:54:24.623 回答
0

“等于”比较对象并返回真或假,如果为真,“比较”返回 0,如果为假,则返回数字 [> 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)

于 2015-05-11T00:52:53.333 回答
0

这里有一件事很重要,而使用compareTo()overequals()compareTo适用于实现“Comparable”接口的类,否则它会抛出一个NullPointerException. String类实现了 Comparable 接口,而StringBuffer没有因此您可以"foo".compareTo("doo")String对象中使用但不能在StringBuffer对象中使用。

于 2018-03-24T04:16:52.723 回答
0
String s1 = "a";
String s2 = "c";

System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));

这打印 -2 和 false

String s1 = "c";
String s2 = "a";
System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));

这打印 2 和 false

String s1 = "c";
String s2 = "c";
System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));

这打印 0 和 true

当且仅当两个字符串都匹配时,equals 返回布尔值。

compareTo 不仅要判断它们是否匹配,还要判断哪个 String 比另一个小,以及按字典顺序小多少。这主要用于在集合中进行排序。

于 2020-04-16T10:15:11.047 回答
-1

我相信返回equalsequalsIgnoreCase方法,如果你想比较字符串对象的值,这很有用,但是在实现和方法的情况下,返回正值、负值和零值,这在排序的情况下很有用。StringtruefalsecompareTocompareToIgnoreCase

于 2019-06-01T08:44:38.233 回答