List를 제외한 Set, Map등의 컬렉션사용 시
객체를 비교하는 contains() 메서드에 대한 중요한 내용
다음 예제를 작성하여 동작확인
package exam;
import java.util.HashSet;
public class Exam {
public static void main(String[] args) {
HashSet hs = new HashSet();
int a = 10;
hs.add(a);
//new Integer(a) auto boxing
int b = 10;
System.out.println(hs.contains(b));
}
}
실행결과는 예상하는 대로 true이다.
이번엔 클래스 자료형이지만 기본 자료형처럼 사용되는 String을 이용하여 확인한다.
package exam;
import java.util.HashSet;
public class Exam {
public static void main(String[] args) {
HashSet hs = new HashSet();
String a = "hello";
String b = new String(new char[] { 'h', 'e', 'l', 'l', 'o' });
hs.add(a);
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(hs.contains(b));
}
}
실행결과
a가 참조하는 String객체와 b가 참조하는 String객체는 서로 다른 객체이므로 false
equals메서드는 String에 오버라이딩 되어 있으며 동작은 내부의 문자들을 비교하므로 true
HashSet객체에 a만 추가했지만 b와 같은 문자열을 가졌으므로 동일한 객체가 존재한다는 true
하지만 다음 예제를 통해 확인하면 무언가 다른 개념이 있음을 알 수 있다.
package exam;
import java.util.HashSet;
class Custom {
int x;
Custom(int x) {
this.x = x;
}
}
public class Exam {
public static void main(String[] args) {
HashSet hs = new HashSet();
Custom a = new Custom(10);
Custom b = new Custom(10);
hs.add(a);
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(hs.contains(b));
}
}
실행결과
앞에서 String클래스의 객체를 이용할 때 true이던 결과가 모두 false이다.
일단 equals메서드는 오버라이딩이 필요하므로 다음과 같이 Custom클래스에 equals를 정의한다.
(이클립스의 source매뉴 활용해도 됨)
package exam;
import java.util.HashSet;
class Custom {
int x;
Custom(int x) {
this.x = x;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Custom other = (Custom) obj;
if (x != other.x)
return false;
return true;
}
}
public class Exam {
public static void main(String[] args) {
HashSet hs = new HashSet();
Custom a = new Custom(10);
Custom b = new Custom(10);
hs.add(a);
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(hs.contains(b));
}
}
그리고 다시 실행해보면 다음과 같은 결과가 나온다.
Set, Map 등의 컬렉션으로 객체를 관리할 때 객체를 고유하게 식별하기 위해 hashCode()를 이용한다. hashCode()는 객체를 생성할 때 JVM을 통해 정해지는 객체 식별 값이다.
Object의 equals메서드는 객체자체를 비교하는 것이 아니라 객체가 가진 값을 비교하는 용도이며
Set, Map은 contains()메서드 사용 시 객체를 식별하는 hashCode 값을 이용하여 객체 자체를 비교한다.
이를 확인을 위해 Custom클래스에 hashCode()메서드를 재정의하고 실행결과를 본다.
package exam;
import java.util.HashSet;
class Custom {
int x;
Custom(int x) {
this.x = x;
}
@Override
public int hashCode() {
System.out.println("hashCode() 호출");
final int prime = 31;
int result = 1;
result = prime * result + x;
return result;
}
@Override
public boolean equals(Object obj) {
System.out.println("qeuals() 호출");
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Custom other = (Custom) obj;
if (x != other.x)
return false;
return true;
}
}
public class Exam {
public static void main(String[] args) {
HashSet hs = new HashSet();
Custom a = new Custom(10);
Custom b = new Custom(10);
hs.add(a);
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(hs.contains(b));
}
}
실행결과
contains메서드 호출 시 hashCode()메서드와 equals()메서드를 이용한다는 것을 확인할 수 있다.
List계열은 객체의 중복을 허용한다. 따라서 equals()만 사용함.
이를 확인하기 위해 HashSet을 ArrayList로 변경하여 실행해본다.
package exam;
//import java.util.HashSet;
import java.util.ArrayList;
class Custom {
int x;
Custom(int x) {
this.x = x;
}
@Override
public int hashCode() {
System.out.println("hashCode() 호출");
final int prime = 31;
int result = 1;
result = prime * result + x;
return result;
}
@Override
public boolean equals(Object obj) {
System.out.println("qeuals() 호출");
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Custom other = (Custom) obj;
if (x != other.x)
return false;
return true;
}
}
public class Exam {
public static void main(String[] args) {
// HashSet hs = new HashSet();
ArrayList al = new ArrayList();
Custom a = new Custom(10);
Custom b = new Custom(10);
//hs.add(a);
al.add(a);
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(al.contains(b));
}
}
실행결과
equals()메서드만 사용해서 객체의 값만 확인하는 것을 볼 수 있다.
'교육자료 > Java' 카테고리의 다른 글
Java Thread (쓰레드) (0) | 2017.06.30 |
---|---|
Java Exception(예외처리) (0) | 2017.06.28 |
Java Collection part1 (0) | 2017.06.27 |
Java 인터페이스 (interface) (0) | 2017.06.25 |
Java 추상 클래스(abstract class) (0) | 2017.06.25 |