자바 HashMap - 개발자가 정의한 class를 key로 만드는 방법

자바의 HashMap은 파이썬의 dict처럼, 고유한 key와 대응하는 value를 하나의 쌍으로 하여, 저장하는 자료구조

 

일반적으로 key를 문자열, 정수값으로 사용하지만, 필요에 따라 특정한 class를 key로 하고 싶을 수 있다

 

시험에 아래와 같은 Point라는 클래스를 key로 하고 싶었는데...

 

class Point {
	int x,y;
	
	public Point(int x, int y) {
		this.x = x;
		this.y = y;
	}
}

 

이걸 HashMap의 key로 사용해서 자료를 관리해볼려 했는데.. 원하는대로 동작을 안하더라고?

 

그립습니다 파이썬님

 

 

 

자연스럽게 두 객체 p1, p가 같다는 것은 x,y가 서로 같다는 것인데..

 

문제는 key로 사용한 p1의 주소와 get을 하면서 넣은 p의 주소가 달라서 자바가 서로 같은 객체라고 인식을 못하더라

 

그래서 p1을 넣는다면 1을 출력하긴 함

 

하지만 알고리즘에서 p1을 그대로 쓸수 있는 경우는 드물지

 

그래서 새로 Point(1,2)를 만들어서 넣어도 이전에 넣은 value를 뽑아내길 원하는데...

 

 

이런 문제를 해결하고 싶다면, 사용자 정의한 클래스에서 equals와 hashCode 함수를 override해줘야한다.

 

equals는 객체의 동일성을 직접 정의하면 된다

 

x,y가 서로 같다면 동일하다고 정의하고 싶을때... equals 함수를 다음과 같이 정의하면 된다

 

	@Override
	public boolean equals(Object o) {
		if(this == o) {
			return true;
		}
		
		if(o == null || this.getClass() != o.getClass()) {
			return false;
		}
		
		Point other = (Point) o;
		
		return other.x == x && other.y == y;
	}

 

어떤 임의의 객체 o를 받더라도, equals 함수가 작동할 수 있도록 만드는듯..?

 

this == o라는 것은 p1.equals(p1)같이 동일한 객체를 비교할때... 얘는 true니까

 

o == null이 들어오거나, getClass()는 객체의 class정보를 알 수 있는 메소드인데 Point 클래스 정보랑, 들어온 객체 클래스 정보가 다르다면, false를 return

 

그 외의 경우에는... 실제 x값과 y값이 서로 같은지 비교해서 그 여부를 return을 해준다

 

-------------------------------------------------------------------------------------------------------------------------------------

 

혹은 다음과 같이 구현하는 경우도 있더라

 

(객체) instanceof (클래스)는 해당 객체가 클래스에 속하는지 여부,

 

해당 클래스로 형변환 가능한지 여부(예: 상속받은 경우?)를 true/false로 return하는데

 

[JAVA] 자바_instanceof (객체타입 확인) (tistory.com)

 

[JAVA] 자바_instanceof (객체타입 확인)

- 객체 타입 확인 instanceof - instanceof - instanceof는 객체 타입을 확인하는 연산자이다. - 형변환 가능 여부를 확인하며 true / false로 결과를 반환한다. - 주로 상속 관계에서 부모객체인지 자식 객체인

mine-it-record.tistory.com

 

o instance of Point 하면 o가 Point 클래스인지 확인하는 것으로..

 

이게 더 직관적인것 같은데?

 

	@Override
	public boolean equals(Object o) {
		if(!(o instanceof Point)) {
			return false;
		}
		Point other = (Point) o;
		
		return other.x == this.x && other.y == this.y;
	}

 

다음은 hashCode()함수를 정의해야 한다.

 

최대한 중복되지 않고, 다양한 값을 반환할 수 있어야 하며, 동시에 서로 같은 값이라고 한다면 같은 hashCode값을 반환해야한다.

 

위의 예시에서 p1과 p의 hashCode가 같게 나와야 p1,p가 같다고 인식하게 된다.

 

이런 조건을 만족하게 hashcode를 정의하면 되긴하지만.. Objects 라이브러리에 hash함수를 사용해서 다음과 같이 간단하게 정의할 수 있다

 

	@Override
	public int hashCode() {
		return Objects.hash(this.x,this.y);
	}

 

따라서 Point를 다음과 같이 정의하고 진짜로 HashMap이 내가 원하는대로 동작하는지 테스트해본다면..?

 

import java.util.Objects;

class Point {
	int x,y;
	
	public Point(int x, int y) {
		this.x = x;
		this.y = y;
	}
	
//	@Override
//	public boolean equals(Object o) {
//		if(this == o) {
//			return true;
//		}
//		
//		if(o == null || this.getClass() != o.getClass()) {
//			return false;
//		}
//		
//		Point other = (Point) o;
//		
//		return other.x == x && other.y == y;
//	}
	
	@Override
	public boolean equals(Object o) {
		if(!(o instanceof Point)) {
			return false;
		}
		Point other = (Point) o;
		
		return other.x == this.x && other.y == this.y;
	}
	
	@Override
	public int hashCode() {
		return Objects.hash(this.x,this.y);
	}
}

 

 

와 진짜 되네..?

 

이걸 알았다면 합격이었을까..?--

 

 

 

Java에서 HashMap을 위한 Custom Key 정의하기 – GIS Developer

 

Java에서 HashMap을 위한 Custom Key 정의하기 – GIS Developer

Java의 HashMap 자료구조는 고유한 값인 Key와 1:1로 연관되는 값(Value)을 하나의 쌍(Pair)로 하여 여러 개의 쌍을 저장하는 자료구조입니다. 흔히 Key 값으로 문자열이나 정수값을 사용하는 것으로도 충

www.gisdeveloper.co.kr

 

[Java] 자바 - Object클래스와 메소드, equals(), toString(), getClass() :: KADOSHoly (tistory.com)

 

[Java] 자바 - Object클래스와 메소드, equals(), toString(), getClass()

자바 - Object클래스와 메소드, equals(), toString(), getClass() Object클래스는 자바에서 모든 클래스들의 최상위 조상 클래스입니다. 따라서 자바에서 만들어지는 모든 클래스는 따로 선언하지 않아도 기

kadosholy.tistory.com

 

What issues should be considered when overriding equals and hashCode in Java? - Stack Overflow

 

What issues should be considered when overriding equals and hashCode in Java?

What issues / pitfalls must be considered when overriding equals and hashCode?

stackoverflow.com

 

 

TAGS.

Comments