Java字符串:compareTo()与equals()

在Java中测试 String 的相等性时,我总是使用 equals() ,因为对我而言,这似乎是最自然的方法 . 毕竟,它的名字已经说明了它的目的 . 然而,我最近告诉我的一位同事被教导使用 compareTo() == 0 而不是 equals() . 这感觉不自然(因为 compareTo() 是为了提供一个排序而不是相等的平等),甚至有点危险(因为 compareTo() == 0 并不一定意味着在所有情况下都是平等的,即使我知道它对_1146085的确是如此) .

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

回答(19)

3 years ago

区别在于 "foo".equals((String)null) 返回false而 "foo".compareTo((String)null) == 0 抛出NullPointerException . 所以即使对于Strings来说,它们也不总是可以互换的 .

3 years ago

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

compareTo() 还有一个缺点,即它只适用于实现 Comparable 接口的对象 .

这通常适用于字符串 .

3 years ago

两个主要区别是:

  • equals 会将任何Object作为参数,但 compareTo 将只接受字符串 .

  • equals 仅告诉您它们是否相等,但 compareTo 提供了字符串按字典顺序进行比较的信息 .

我看了the String class code,compareTo和equals中的算法看起来基本相同 . 我相信他的观点只是一个品味问题,我同意你的看法 - 如果您需要知道的是字符串的相等性而不是首先按字典顺序排列,那么我会使用 equals .

3 years ago

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

3 years ago

在String上下文中:
compareTo:按字典顺序比较两个字符串 .
equals:将此字符串与指定对象进行比较 .

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

3 years ago

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

But compareTo() gives the ordering of objects ,通常用于按升序或降序排序对象,而 equals() will only talk about the equality 并说明它们是否相等 .

3 years ago

equals()可以比compareTo()更高效 .

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

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

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

compareTo() (来自Comparable接口)返回一个整数 . 它检查两个对象中的哪一个是"less than","equal to"或"greater than"另一个 . 并非所有对象都可以按逻辑顺序排列,因此compareTo()方法并不总是有意义 .

请注意,equals()不定义对象之间的顺序,compareTo()也是如此 .

现在我建议你检查两种方法的源代码,得出结论,equals比compareTo更可取,这涉及一些数学计算 .

3 years ago

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

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

3 years ago

equals() 应该是OP的选择方法 .

查看java.lang.String on grepcodeequals()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          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() 找到词法排序 .

3 years ago

在Java中覆盖compareTo时,您需要记住某些事项,例如Compareto必须与equals和subtraction一致,不应该用于比较整数字段,因为它们可以溢出 . 检查Things to remember while overriding Comparator in Java了解详情 .

3 years ago

Equals可以比compareTo更有效 .

如果String中字符序列的长度不匹配,则字符串无法相等,因此拒绝可以更快 .

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

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

3 years ago

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

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

该测试比较了1000个元素阵列中的每个字符串,重复10次 .

3 years ago

  • equals 可以将任何Object作为参数,但 compareTo 只能接受String .

  • 当到达null时, compareTo 将抛出异常

  • 当你想知道差异发生的地方时,你可以使用 compareTo .

3 years ago

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

大多数答案比较性能和API差异 . 他们错过了两个操作只具有不同语义的基本点 .

你的直觉是正确的 . x.equals(y)不能与x.compareTo(y)== 0互换 . 第一个比较身份,而另一个比较'size'的概念 . 确实,在许多情况下,尤其是原始类型,这两个共同对齐 .

一般情况是这样的:

如果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:

当且仅当a1 = a2且b1 = b2时,Z1.equals(z2)才返回true .

然而,只要满足条件a1 ^ 2 b1 ^ 2 == a2 ^ 2 b2 ^ 2,Z1.compareTo(Z2)就返回0和无限数量的(a1,b1)和(a2,b2)对 .

3 years ago

  • equals :检查相等性和限制重复项所必需的 . 许多Java库类都使用它,以防他们想要查找重复项 . 例如 HashSet.add(ob1) 只会在不存在的情况下添加 . 因此,如果您正在扩展这样的类,则覆盖 equals() .

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

3 years ago

Equals -

1-重写GetHashCode方法以允许类型在哈希表中正常工作 .

2-不要在实现Equals方法时抛出异常 . 相反,为null参数返回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

compareTo -

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

它返回 -

小于零 - 此实例在排序顺序中位于obj之前 . 零 - 此实例出现在排序中的相同位置订购为obj . 大于零 - 此实例遵循排序顺序中的obj .

如果object与实例的类型不同,它可以抛出ArgumentException .

例如,您可以访问此处 .

所以我建议用Equals代替compareTo .

3 years ago

“equals”比较对象并返回true或false,“compare to”返回0 if为true或数字[> 0]或[<0]如果为false则为例如:

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

3 years ago

equals()检查两个字符串是否相等 . 它给出了布尔值 . compareTo()检查字符串对象是否等于,大于或小于另一个字符串对象 . 它给出结果如果: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

3 years ago

在使用 compareTo() 而不是 equals() 时,有一件事很重要 compareTo 适用于实现'Comparable'接口的类,否则会抛出 NullPointerException . String 类实现Comparable接口,而 StringBuffer 不实现,因此您可以在 String 对象中使用 "foo".compareTo("doo") 但不能在 StringBuffer 对象中使用 "foo".compareTo("doo") .