Java에서 다음과 같은 operator 또는 메소드로 객체를 비교할 수 있습니다.
==
,!=
연산자equals()
Objects.equlas()
Comparable
Comparator
==, != 연산자
==
, !=
연산자 동일한 객체인지 다른 객체인지 비교할 수 있습니다.
객체가 갖고 있는 value를 비교하는 것이 아니라, 객체가 저장되어있는 메모리 주소를 비교하는 것을 주의해야 합니다.
다음과 같이 Primitive type을 비교할 때는 value만 비교합니다.
int a = 10;
int b = 10;
int c = 11;
System.out.println(a == b);
System.out.println(a != b);
System.out.println(a == c);
Output:
true
false
false
하지만 Primitive type이 아닌 Object를 비교할 때는 value가 아닌 Object의 메모리 주소를 비교합니다.
예를 들어, 아래와 같이 두개의 Integer 객체를 생성하였습니다. 두 객체의 메모리 주소는 다르기 때문에 결과는 false가 됩니다.
Integer a = new Integer(10);
Integer b = new Integer(10);
System.out.println(a == b);
Output:
false
하지만 다음 코드의 결과는 true가 됩니다. 이유는 두 객체는 메모리의 주소가 동일하기 때문입니다.
Integer a = Integer.valueOf(10);
Integer b = Integer.valueOf(10);
System.out.println(a == b);
Output:
true
아래 코드는 Integer.java
의 valueOf(int i)
입니다. 코드를 보시면 캐시되어있는 객체가 있을 때, 새로 생성하지 않고 이전에 만든 객체를 리턴하도록 구현되어있습니다.
이 때문에 위의 두 객체의 메모리 주소가 같은 값을 가리키게 되었습니다.
// Integer.java
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
따라서, 객체 비교에 ==
를 사용하는 것은 예상치 못한 결과를 가져올 수 있습니다.
꼭 사용해야한다면 이런 부분에 주의를 기울여야 합니다.
equals()
equals()
를 이용하면 객체의 value를 비교할 수 있습니다.
Integer a = new Integer(10);
Integer b = new Integer(10);
System.out.println(a.equals(b));
Output:
true
Integer.java
의 equals()
코드를 보면, 객체와 인자로 전달되는 객체의 value를 비교하도록 구현되어있습니다.
public final class Integer extends Number implements Comparable<Integer> {
....
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
}
자신이 직접 정의한 클래스의 객체들을 비교하고 싶다면, 이런 식으로 equals()
를 직접 구현해줘야 합니다.
Objects.equals()
Java는 Objects.equals()
라는 메소드도 제공합니다.
객체의 equals()
를 사용하는 것과 동일한 결과를 리턴합니다.
Integer a = new Integer(10);
Integer b = new Integer(11);
System.out.println(Objects.equals(a, b));
Output:
false
클래스의 equals()
와 차이점은, Objects.java
의 메소드를 보면 null check
코드가 있기 때문에 NullPointerException
은 발생하지 않습니다.
// Objects.java
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
Comparable
다음과 같은 Comparable 인터페이스를 클래스에 implements하여 비교할 수 있습니다.
public interface Comparable<T> {
public int compareTo(T o);
}
compareTo()
는 비교하는 객체가 같거나, 크거나, 작거나를 비교하여 0, 음수, 양수를 리턴할 수 있습니다.
다음과 같이 String을 갖고 있는 Text라는 클래스를 정의하였습니다. Comparable를 implements하여 compareTo()
라는 메소드를 오버라이딩하였습니다.
public class Text implements Comparable<Text> {
private String mText;
public Text(String text) {
mText = text;
}
public String getText() {
return mText;
}
@Override
public int compareTo(Text right) {
return mText.compareTo(right.getText());
}
}
다음과 같이 사용할 수 있습니다.
Text text1 = new Text("aaa");
Text text2 = new Text("aaa");
System.out.println(text1.compareTo(text2));
Output:
0
Comparable
은 객체를 Sorting할 때 사용됩니다.
Comparator
Comparator도 Comparable과 비슷합니다. 차이점은 Comparator는 인터페이스가 아니라 객체로 생성한다는 것입니다.
다음과 같이 객체를 정렬할 때 Comparator를 사용할 수 있습니다. sort()
으로 인자로 전달되어 내부에서 객체가 같은지, 큰지, 작은지 비교하는데 사용합니다.
예제에서는 객체의 주소를 비교하는 것이 아닌, 문자열의 길이를 비교하였습니다.
List<String> strings = new ArrayList<>();
strings.add("This code is free software");
strings.add("you can redistribute it");
strings.add("under the terms of the GNU General Public License version 2 only");
// sorting
Collections.sort(strings, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
});
System.out.println();
for (String str : strings) {
System.out.println(str);
}
Output:
you can redistribute it
This code is free software
under the terms of the GNU General Public License version 2 only
Recommended Posts:
- Java - Locale 클래스
- Java - split()으로 문자열을 자르기
- Java - substring()으로 문자열을 자르기
- Java - List와 Set의 차이점
- Java - forEach 사용 방법
- Java - Thread.join()
- Java - getPath(), getAbsolutePath(), getCanonicalPath()
- Java - Timer, TimerTask
- Java - Number Class
- Java - printf()로 문자열 포맷 출력
- Java - Float을 Byte 배열로 변환, Byte배열을 float으로 변환
- Java - 변수의 유효 범위 (Variable Scope)
- Java - instanceOf 연산자