티스토리 뷰
개요
Collection의 List나 Map은 모두 get()메소드로 저장되어진 인스턴스를 가져올 수 있지만 Set만 get메소드가 존재하지 않습니다. 왤까요..?
1. Set의 본래 사용 목적과 맞지 않는다.
Set은 순서와 상관없이 중복되지 않는 데이터를 저장하는 것을 목적으로 만들어진 자료구조입니다. 순서를 보장하지 않기 때문에 List 처럼 인덱스 값을 가질 수 없습니다. 대신 중복을 허용하지 않기 때문에 해당 데이터가 저장되어 있는지 아닌지를 빠르게 확인하는 contains() 메소드를 가질 수 있습니다. (List도 contains() 메소드를 가지고 있기는 하지만 모든 데이터를 순회하면서 탐색하여 성능이 좋지 않습니다.)
2. 구조적으로 구현이 불가능하다.
Set의 구현체들을 살펴보면 흥미로운 사실을 하나 알게 됩니다. Set은 내부적으로 Map을 사용하여 구현되어 있습니다.
(아래코드는 이해를 위해서 많은 부분이 생략되어진 코드입니다.)
public class HashSet<E> implements Set<E> {
private HashMap<E,Object> map;
public HashSet() {
map = new HashMap<>();
}
}
HashSet은 필드로 HashMap을 가지고 있고, Set에 저장되는 데이터는 내부 HashMap의 Key값으로 저장됩니다. 그리고 Map의 Value에는 의미없는(Dummy) 값이 들어가게 됩니다. (구현체 코드를보면 친절하게 주석으로 설명까지 되어있습니다.)
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
Map의 키값을 get 하는 것이 불가능하기 때문에 Set의 get 메소드는 구현하기가 불가능합니다.
3. Set에게 get은 의미 없는 기능이다.
여전히 Set에서 get 메소드를 사용하고 싶다는 생각은 지워지지 않습니다. 그래서 나만의 Set 구현체를 만들어서 나만 편하게 get 메소드를 써야겠다는 생각으로 직접 구현해보기 시작했습니다.
하지만 이 의문과 호기심이 을마나 세상 바보같았는지 바로 알 수 있었습니다.
Set의 get()메소드를 사용한다고 가정해보겠습니다.
Set<Integer> integers = new HashSet();
integers.add(3);
Integer get = integers.get(3); //이미 매개변수로 들어가는 값이 얻고자 하는 인스턴스와 같다.
get 하고자 하는 인스턴스와 equals()한 인스턴스를 이미 매개변수로 가지고 있기 때문에 get 행위자체가 의미가 없으며, 만약 일부분만 동일한 데이터를 이용해서 저장된 인스턴스를 얻고자 한다면 Map의 키와 밸류로 저장되는 것이 바람직한 사용방법입니다.
참고자료
'Java' 카테고리의 다른 글
String은 항상 StringBuilder로 변환될까? (4) | 2020.04.01 |
---|---|
EnumSet이 new 연산자를 사용하지 않는 이유 (0) | 2019.09.12 |
EnumMap(EnumSet) 쓰면 좋을까? (vs HashMap) (2) | 2019.06.06 |
내부(inner) class와 내부(inner) static class 차이 (7) | 2019.06.02 |
Java에서 원시타입 vs 참조타입 어떤 걸 사용해야 할까? (0) | 2019.05.19 |