compareTo () 대 equals ()


118

StringJava에서의 동등성을 테스트 할 때 나는 equals()이것이 가장 자연스러운 방법 인 것처럼 보이기 때문에 항상 사용 했습니다. 결국 그 이름은 이미 의도 한 바를 말하고 있습니다. 그러나 최근에 동료 compareTo() == 0equals(). 이것은 부자연스럽고 ( compareTo()순서를 제공하고 평등을 비교하지 않기위한 것이므로) 다소 위험하다고 느껴집니다 (왜냐하면 compareTo() == 0모든 경우에 평등을 의미하지는 않기 때문입니다 String).

그가 사용하는 배웠습니다 그는 왜 몰랐 compareTo()대신 equals()String의, 나는 또한 어떤 이유를 찾을 수 없습니다. 이것은 정말로 개인적인 취향의 문제입니까, 아니면 두 방법 모두에 대한 진정한 이유가 있습니까?


9
우리가 너무 일찍 말해서는 안되는 마이크로 최적화 수준에서 엄격하게 말하는 .equalsIgnoreCase()것이 적절하다면 가장 빠른 비교이고 그렇지 않으면 .equals()원하는 것입니다.

1
이것은 오래된 질문이지만 제가 강조하고 싶은 부분이 있습니다. " compareTo() == 0모든 경우에 반드시 평등을 의미하지는 않습니다." 이것은 절대적으로 정확합니다! 이것이 바로 Java API 사양 (예 : Comparable 클래스 사양) 에서 "일관된 일치"라는 문구가 의미하는 바입니다 . 예를 들어, String의 비교 방법은 같음과 일치하지만 BigDecimal의 비교 방법은 같음과 일치하지 않습니다 .
Stuart Marks

답변:


104

차이점은 NullPointerException "foo".equals((String)null)"foo".compareTo((String)null) == 0throw하는 동안 false 를 반환 한다는 것 입니다. 따라서 문자열에서도 항상 교환 할 수있는 것은 아닙니다.


6
이것도 언급해야한다고 생각합니다. 같음은 해시 코드를 계산합니다. 드물기는하지만 두 개의 서로 다른 문자열의 해시 코드는 동일 할 수 있습니다. 그러나 compareTo ()를 사용하면 문자열을 문자별로 확인합니다. 따라서이 경우 두 문자열은 실제 내용이 동일한 경우에만 true를 반환합니다.
애쉬 윈

30
왜 그것이 해시 코드를 계산한다고 생각합니까? 이 경우가 아님을 알 수 있습니다. docjar.com/html/api/java/lang/String.java.html(1013 행).
waxwing

3
당신이 옳습니다. 나는 같음과 해시 코드가 손을 잡고 있다고 생각했습니다 (같음은 둘 다 동일한 해시 코드를 가지고 있는지 확인합니다). 그렇다면 둘 중 하나를 재정의하기로 결정한 경우 두 가지 방법을 모두 재정의해야하는 이유는 무엇입니까?
Ashwin 2012-06-07

3
클래스가 HashMap, HashSet 및 Hashtable을 포함한 해시 기반 컬렉션을 사용하면 클래스가 제대로 작동하지 않기 때문에 equals를 재정의 할 때 해시 코드를 재정의해야합니다
varunthacker

4
@Ashwin .equals가 true를 반환하면 해시 코드도 같아야하기 때문에 필요합니다. 그러나 해시 코드가 같으면 .equals가 true를 반환해야 함을 의미하지는 않습니다
Alan

33

두 가지 주요 차이점은 다음과 같습니다.

  1. equals모든 개체를 매개 변수로 사용하지만 compareTo문자열 만 사용합니다.
  2. equals동일한 지 여부 만 알려주지 만 compareTo문자열이 사 전적으로 비교되는 방법에 대한 정보를 제공합니다.

String 클래스 코드를 살펴 보았고 compareTo 및 equals 내의 알고리즘은 기본적으로 동일하게 보입니다. 나는 그의 의견이 단지 취향의 문제라고 믿고, 나는 당신에게 동의합니다. 만약 당신이 알아야 할 모든 것이 Strings의 평등이고 어떤 것이 어휘 학적으로 먼저 오는 것이 아니라면, 나는 equals.


26

평등을 비교할 때는 equals()의도를 분명하게 표현하기 때문에 를 사용해야합니다 .

compareTo()Comparable인터페이스 를 구현하는 객체에서만 작동한다는 추가 단점이 있습니다.

이것은 문자열뿐만 아니라 일반적으로 적용됩니다.


18

compareTo문자열의 길이가 다른 경우 더 많은 작업을 수행합니다. equalsfalse를 반환 compareTo할 수 있지만 정렬 순서를 찾기 위해 항상 충분한 문자를 검사해야합니다.


10

compareTo()compareTo<T>일반 인수를 취하기 때문에 문자열뿐만 아니라 다른 모든 객체에도 적용됩니다 T. String은 다음을 구현하여 compareTo()메서드를 구현 한 클래스 중 하나입니다 .Comparable 인터페이스를 . (compareTo ()는 유사한 인터페이스를위한 메서드입니다). 따라서 모든 클래스는 Comparable 인터페이스를 자유롭게 구현할 수 있습니다.

그러나compareTo() 일반적으로 오름차순 또는 내림차순으로 객체를 정렬하는 데 사용되는 객체의 순서를 제공하며 equals()평등에 대해서만 이야기하고 동일한 지 여부를 말합니다.


10

문자열 컨텍스트에서 :
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

7

equals ()compareTo () 보다 더 효율적일 수 있습니다 .

compareTo와 equals의 매우 중요한 차이점 :

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

equals () 는 두 객체가 동일한 지 확인하고 부울을 반환합니다.

compareTo () (Comparable 인터페이스에서) 정수를 반환합니다. 두 개체 중 어떤 개체가 다른 개체보다 "작거나", "같거나" "큰지"확인합니다. 모든 객체를 논리적으로 정렬 할 수있는 것은 아니므로 compareTo () 메서드가 항상 의미가있는 것은 아닙니다.

equals ()는 compareTo ()가하는 객체 사이의 순서를 정의하지 않습니다.

이제 두 방법의 소스 코드를 검토하여 일부 수학 계산이 포함 된 compareTo보다 equals가 더 낫다는 결론을 내리는 것이 좋습니다.


5

두 메서드가 거의 동일한 작업을 수행하는 것처럼 보이지만 compareTo () 메서드는 Object가 아닌 String을 가져와 일반 equals () 메서드 위에 몇 가지 추가 기능을 추가합니다. 당신이 관심을 가지는 것이 평등 인 경우, equals () 메서드가 최선의 선택입니다. 단순히 코드를 살펴 보는 다음 프로그래머에게 더 의미가 있기 때문입니다. 엄청난 양의 항목을 반복하지 않는 한 두 가지 다른 기능 간의 시간 차이는 중요하지 않습니다. compareTo ()는 컬렉션에서 문자열의 순서를 알아야하거나 동일한 문자 시퀀스로 시작하는 문자열 간의 길이 차이를 알아야 할 때 정말 유용합니다.

출처 : http://java.sun.com/javase/6/docs/api/java/lang/String.html


5

equals() OP의 경우 선택하는 방법이어야합니다.

의 구현을 보면 equals()compareTo()grepcode에 java.lang.String의 , 우리는 쉽게 우리가 두 문자열의 평등에 관심을하는 경우 등호 더 낫다고 볼 수 있습니다 :

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 = 카운트;
1019 if (n == anotherString.count) {
1020 char v1 [] = value;
1021 char v2 [] = anotherString.value;
1022 정수i = 오프셋;
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 = 또 다른 String.count;
1177 int n = 수학. min (len1, len2);
1178 char v1 [] = 값;
1179 char v2 [] = anotherString.value;
1180 int i = 오프셋;
1181 int j = 또 다른 String.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 문자 c2 = v2 [j ++];
1198 if (c1! = c2) {
1199 return c1-c2;
1200 }
1201 }
1202
1203 반환len1-len2;
1204 }

문자열 중 하나가 다른 문자열의 접두사 인 경우, 더 이상 걱정하지 않고 즉시 false를 반환 compareTo()하는 동안 사전 순서를 결정해야하므로 성능 이 더 나빠집니다 equals().

제 생각에는이 두 가지를 의도 한대로 사용해야합니다.

  • equals() 평등을 확인하고
  • compareTo() 어휘 순서를 찾습니다.

3

equals ()는 두 문자열이 같은지 확인하고 부울 값을 제공합니다. compareTo ()는 문자열 객체가 다른 문자열 객체보다 크거나 작은 지 확인합니다. 문자열 객체가 다른 문자열보다 크면 0보다 크면 1과 같은 결과를 제공합니다. 문자열이 다른 문자열보다 작 ​​으면 -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


2

이것은 강령술의 실험입니다 :-)

대부분의 답변은 성능과 API 차이를 비교합니다. 두 연산이 단순히 다른 의미를 갖는다는 근본적인 요점을 놓칩니다.

당신의 직감이 맞습니다. x.equals (y)는 x.compareTo (y) == 0과 교환 할 수 없습니다. 첫 번째는 동일성을 비교하고 다른 하나는 '크기'개념을 비교합니다. 많은 경우, 특히 기본 유형의 경우이 두 가지가 함께 정렬되는 것은 사실입니다.

일반적인 경우는 다음과 같습니다.

x와 y가 동일하면 동일한 '크기'를 공유합니다. x.equals (y)가 true이면 => 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를 반환합니다.

그러나 Z1.compareTo (Z2)는 조건 a1 ^ 2 + b1 ^ 2 == a2 ^ 2 + b2 ^ 2를 만족하는 한 무한한 수의 (a1, b1) 및 (a2, b2) 쌍에 대해 0을 반환합니다.


1
x.equals (y)는 신원을 의미하지 않고 평등을 의미합니다. ID는 Java의 사용자 정의 유형에 대해 x == y를 사용하여 비교됩니다.
Fernando Pelliccioni

2

Equals는 compareTo보다 더 효율적일 수 있습니다.

문자열의 문자 시퀀스 길이가 일치하지 않으면 문자열이 같을 수 없으므로 거부가 훨씬 빨라질 수 있습니다.

또한 동일한 객체 (논리적 평등보다는 정체성 평등)이면 더 효율적일 것입니다.

또한 hashCode 캐싱을 구현 한 경우 hashCode가 일치하지 않는 경우 같지 않은 항목을 거부하는 것이 더 빠를 수 있습니다.


2

String.equals()호출 instanceof연산자가 compareTo()필요 하지만 필요하지 않습니다. 내 동료는 메서드 instanceof에서 과도한 수의 호출 로 인한 큰 성능 저하를 지적 equals()했지만 내 테스트는 compareTo()약간 더 빠르다 는 것이 입증 되었습니다.

그러나 Java 1.6을 사용하고있었습니다. 다른 버전 (또는 다른 JDK 공급 업체)에서는 차이가 더 클 수 있습니다.

이 테스트는 1000 개의 요소 배열에서 각 문자열을 10 번 반복하여 비교했습니다.


1
compareTo()더 빠른 결과를 얻으려면 첫 번째 문자에서 길이가 같고 다양성이 높은 매우 짧은 문자열을 사용했을 것입니다 equals(). 그러나 대부분의 실제 데이터 세트의 equals()경우 compareTo() == 0. equals()문자열에 공통 접두사가 있지만 길이가 다르거 나 실제로 동일한 객체 인 경우 빛납니다.
x4u 2011-06-03

글쎄, 내 테스트는 instanceof가 성능 킬러라는 가설에 반하는 것이기 때문에 문자열이 실제로 짧았습니다.
Danubian Sailor

문자열이 무작위이고 길이가 대부분 다른 경우, 대부분의 경우 길이가 같지 않으면 즉시 false를 반환하므로보다 확실한 선택은 compareTo ()보다 equals () 메서드 여야합니다.
sactiw

1
  1. equals모든 Object를 매개 변수로 사용할 compareTo수 있지만 String 만 사용할 수 있습니다.

  2. null이되면 compareTo예외가 발생합니다.

  3. diff가 어디에서 발생하는지 알고 싶을 때 compareTo.


compareTo는 모든 개체를 인수로 사용할 수 있습니다. @apurva jadhav가 위에서 말했듯이, compare는 일반적인 인수를 취합니다. Comparable <String>으로 comaparable을 구현하면 문자열 만 사용할 수 있습니다.
Gaurav Kumar

1
  • equals: 동일성을 확인하고 중복을 제한하는 데 필요합니다. Java Library의 많은 클래스는 중복을 찾고자 할 때 이것을 사용합니다. 예를 들어 HashSet.add(ob1)존재하지 않는 경우에만 추가됩니다. 따라서 이와 같은 일부 클래스를 확장하는 경우 equals().

  • compareTo: 요소 주문에 필요합니다. 다시 안정적인 정렬을 위해서는 동등성이 필요하므로 0이 반환됩니다.


0

같음-

1- 해시 테이블에서 형식이 올바르게 작동하도록 GetHashCode 메서드를 재정의합니다.

2- Equals 메서드 구현에서 예외를 throw하지 마십시오. 대신 null 인수에 대해 false를 반환합니다.

삼-

  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 구현은 두 개체가 동일한 인스턴스가 아니더라도 동일한 값을 갖는 경우 true를 반환합니다.

예를 들어-

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

출력 :-

False
True

compareTo 동안 -

현재 인스턴스를 동일한 유형의 다른 개체와 비교하고 현재 인스턴스가 다른 개체와 정렬 순서에서 동일한 위치에 선행하는지, 뒤 따르는 지 또는 동일한 위치에서 발생 하는지를 나타내는 정수를 반환합니다.

반환-

0 미만-이 인스턴스는 정렬 순서에서 obj보다 우선합니다. 0-이 인스턴스는 정렬 순서에서 obj와 동일한 위치에서 발생합니다. 0보다 큼-이 인스턴스는 정렬 순서에서 obj를 따릅니다.

객체가 인스턴스와 동일한 유형이 아닌 경우 ArgumentException을 throw 할 수 있습니다.

예를 들어 여기를 방문 할 수 있습니다.

따라서 compareTo 대신 Equals를 사용하는 것이 좋습니다.


방법이 없습니다 GetHashCode(). 의미 hashCode()합니까?
Marquis of Lorne

0

"equals"는 객체를 비교하고 true 또는 false를 반환하고 "compare to"는 true이면 0을 반환하고 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)


0

여기서는 'Comparable'인터페이스를 구현하는 클래스에서 작동 하는 compareTo()over equals()를 사용하는 동안 중요 compareTo합니다 NullPointerException. 그렇지 않으면 . String클래스 구현에 Comparable 인터페이스 동안은 StringBuffer따라서 당신은 사용할 수 없습니다 "foo".compareTo("doo")String객체가 아니라에서 StringBuffer개체입니다.


0
String s1 = "a";
String s2 = "c";

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

이것은 -2와 거짓을 인쇄합니다.

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

이것은 2와 거짓을 인쇄합니다

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

이것은 0과 true를 인쇄합니다.

같음은 두 문자열이 모두 일치하는 경우에만 부울을 반환합니다.

compareTo는 일치하는지 여부를 알려주는 것뿐만 아니라 어떤 문자열이 다른 문자열보다 작은 지, 그리고 어휘 적으로 얼마나 많은지 알려줍니다. 이것은 컬렉션에서 정렬하는 동안 주로 사용됩니다.


-1

나는 생각 equalsequalsIgnoreCase방법 String반환 true하고 false당신이 문자열 객체의 값을 비교하기를 원한다면 유용하다,하지만 구현의 경우 compareTocompareToIgnoreCase긍정적, 부정적 및 정렬의 경우에 도움이 될 것입니다 값이 0 방법 돌아갑니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.