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

时间:2009-10-11 17:35:17

标签: java string equals compareto

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

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

21 个答案:

答案 0 :(得分:95)

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

答案 1 :(得分:26)

两个主要区别是:

  1. equals会将任意对象作为参数,但compareTo只会使用字符串。
  2. equals只会告诉您它们是否相等,但compareTo会提供有关字符串如何按字典顺序进行比较的信息。
  3. 我看了the String class code,compareTo和equals中的算法看起来基本相同。我相信他的观点只是一个品味问题,我同意你的意见 - 如果您需要知道的是字符串的相等性而不是首先按字典顺序排列,那么我会使用equals

答案 2 :(得分:26)

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

compareTo()的另一个缺点是它只适用于实现Comparable接口的对象。

这一般适用于弦乐。

答案 3 :(得分:16)

如果字符串长度不同,

compareTo会做更多的工作。 equals只能返回false,而compareTo必须始终检查足够的字符才能找到排序顺序。

答案 4 :(得分:10)

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

但是compareTo()给出了对象的排序,通常用于按升序或降序排序对象,而 equals()只会讨论等式并说出他们是否平等。

答案 5 :(得分:10)

在字符串上下文中:
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

答案 6 :(得分:7)

  

等于()可以比 compareTo()更有效。

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

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

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

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

请注意,equals()没有定义对象之间的顺序,compareTo()就是这样。

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

答案 7 :(得分:5)

在OP的情况下,

equals()应该是首选方法。

java.lang.String on grepcode中查看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 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()找到词汇排序。

答案 8 :(得分:5)

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

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

答案 9 :(得分:2)

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

答案 10 :(得分:2)

Equals可以比compareTo更有效。

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

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

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

答案 11 :(得分:2)

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

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

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

答案 12 :(得分:1)

  1. equals可以将任何Object作为参数,但compareTo只能使用String。

  2. 当cometo null时,compareTo将抛出异常

  3. 当您想知道差异发生的位置时,您可以使用compareTo

答案 13 :(得分:1)

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

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

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

一般情况如下:

如果x和y相同,则它们共享相同的“大小”:如果x.equals(y)为true =&gt; 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,Z1.compareTo(Z2)将返回0和无限数量的(a1,b1)和(a2,b2)对。 ^ 2

答案 14 :(得分:1)

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

  • compareTo:       订购元件所需。再次对于稳定排序,您需要相等,因此返回0。

答案 15 :(得分:1)

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

,则返回-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

答案 16 :(得分:0)

等于 -

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。

答案 17 :(得分:0)

&#34;等于&#34;比较对象并返回true或false &#34;与&#34;比较返回0如果为真或数字[&gt; 0]或[&lt; 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)

答案 18 :(得分:0)

使用<IfModule mod_rewrite.c> <IfModule mod_negotiation.c> Options -MultiViews -Indexes </IfModule> RewriteEngine On # Handle Authorization Header RewriteCond %{HTTP:Authorization} . RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] # Redirect Trailing Slashes If Not A Folder... RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} (.+)/$ RewriteRule ^ %1 [L,R=301] # Handle Front Controller... RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] </IfModule> 而不是compareTo()时,有一点很重要equals()适用于实现'Comparable'接口的类,否则会抛出compareToNullPointerException类实现了Comparable接口而String没有,因此您可以在StringBuffer对象中使用"foo".compareTo("doo")但不能在String对象中使用。

答案 19 :(得分:0)

我相信String的 equals and equalingnorecase 方法会返回true和false,这在您想比较字符串对象的值时非常有用,但是在实现 compareTo和compareToIgnoreCase 的情况下strong>方法返回正,负和零值,这在排序时很有用。

答案 20 :(得分: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比另一个String小。通常在集合排序时使用。