자바로 파이썬의 다중데이터 키를가지는 딕셔너리 구현하기

LiiNi·2025년 2월 6일

코드

public class Omok {
	class Key{
		private final int part1;
		private final int part2;
		
		public Key(int a, int b) {
			part1 = a;
			part2 = b;
		}
        //HashMap의 동일연산을 처리하기 위해선 equals()와 HashCode()를 재정의해줘야한다.
		@Override
		public boolean equals(Object obj) {
			if(this == obj) return true;
            //obj의 실제 메모리상의 클래스가 같은지도 판단해야한다(다음라인부터 안전한 캐스팅이 가능해짐)
			if (obj == null || getClass() != obj.getClass()) {
				return false;
			}
			Key target = (Key)obj;
			return (target.part1 == part1 && target.part2 == part2);
		}
        //Objects.hash(T ...)는 내부적으로 Arrays.hash()를 활용한다
		@Override
		public int hashCode() {
			return Objects.hash(part1, part2);
		}
		@Override
		public String toString() {
			return "Key [part1=" + part1 + ", part2=" + part2 + "]";
		}
		
	}
	public static void main(String[] args) {
		Omok o = new Omok(); // 아래 new Key()를 하기 위해서 필요하다
		Map<Key, Integer> dp = new HashMap<>();
		dp.put(o.new Key(1, 3), 4); // o.을 안쓰면 에러난다
		dp.put(o.new Key(1, 3), 5);
		dp.put(o.new Key(1, 10), 10);
		for (Map.Entry<Key, Integer> entry : dp.entrySet()) {
			Key key = entry.getKey();
			Integer val = entry.getValue();
			System.out.println(key + " / "+val);
		}
	}
}
/*
출력결과
Key [part1=1, part2=3] / 5
Key [part1=1, part2=10] / 10
*/

방법

  1. Key에 넣을 사용자정의 클래스 생성
  2. 1의 클래스에 equals()hashCode() 오버라이딩
    i. equals()엔 같은 객체인지 / null인지 / 메모리상 클래스가 같은지(getClass()활용) 를 확인
    ii. 모두 확인하면 이제야 멤버변수 각각 비교
    iii. hashCode()Objects.hash(T ...)를 활용한다
  3. 1의 클래스를 토대로 Map<K, V>를 선언 후 사용한다.
  4. Map을 순회하기 위해선 Map.Entry를 활용한다.(이클립스에서 ctrl+space로 formap줄임말을 활용하면 자동완성된다.)

여담

계기

백준2615. 오목을 풀때, 2차원 좌표를 key로 하는 딕셔너리를 만들고싶었다. 파이썬에선 매우 쉽게 튜플화하여 구현하였지만, 자바에선 이 방식이 매우 힘들었다.

다짐

앞으로 이렇게 다중 데이터를 Map의 Key로 넣는 로직은 코테에서 많이 나올것이다. 그러니 이를 꼭 숙지해두자.

의문점

  • getClass() == obj.getClass() 는 메모리상의 객체의 클래스가 같은지 비교하는 것같은데, Class를 반환하는데에 왜 ==을 사용해도 되는거야? getClass().getName().equals(obj.getClass().getName()) 으로 써야 안전한거 아닌가?
    • 참조 타입에 대해 == 연산자는 메모리 주소를 비교합니다. Class 객체의 경우, 같은 클래스에 대해서는 항상 같은 메모리 주소를 가지므로 == 연산자로 비교해도 정확합니다
profile
보안을 겸비하고픈 풀스택개발자

0개의 댓글