Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

자바(Java)에서 커스텀 HashSet을 구현하는 방법


HashSetSet 인터페이스를 구현한 클래스로, 중복 값을 허용하지 않습니다. 또한 HashSet은 동기화되지 않았으며(not synchronized), 스레드에 안전하지 않습니다(not thread-safe). HashSet에 이미 존재하는 요소를 다시 추가하려고 하면 add() 메서드가 false를 반환하며, 해당 중복 요소는 저장되지 않습니다.

HashSet의 선언 구문

public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable

커스텀 HashSet 구현하기

아래 예제에서는 내부적으로 HashMap을 활용하여 커스텀 HashSet(Custom HashSet)을 직접 구현하는 방법을 살펴봅니다. HashMap의 키(key)는 중복을 허용하지 않는다는 특성을 이용하면 Set의 동작을 손쉽게 재현할 수 있습니다. 실제로 자바 표준 라이브러리의 HashSet도 내부적으로 HashMap을 사용하여 구현되어 있습니다.

예제 코드

import java.util.*;

public class CustomHashSetTest extends AbstractSet<Object> {

   private transient HashMap<Object, Object> map;
   // 더미 값으로 사용할 상수 객체
   private static final Object PRESENT = new Object();

   public CustomHashSetTest() {
      map = new HashMap<>();
   }

   @Override
   public boolean add(Object e) {
      // put()이 null을 반환하면 새로운 키(중복 아님)
      return map.put(e, PRESENT) == null;
   }

   @Override
   public Iterator<Object> iterator() {
      return map.keySet().iterator();
   }

   @Override
   public int size() {
      return map.size();
   }

   public static void main(String[] args) {
      CustomHashSetTest set = new CustomHashSetTest();
      set.add("India");
      set.add("Australia");
      set.add("England");
      set.add("India"); // 중복 요소 → 추가되지 않음

      for (Object obj : set) {
         System.out.println(obj);
      }
   }
}

출력 결과

England
Australia
India

출력 결과에서 확인할 수 있듯이 "India"를 두 번 추가했지만 실제로는 한 번만 저장되었습니다. 그 이유는 add() 메서드가 내부적으로 HashMap의 put() 메서드를 호출하는데, 이미 존재하는 키에 대해서는 기존 값(PRESENT)을 반환하기 때문에 null과 비교한 결과가 false가 되어 중복 추가가 차단됩니다.

이처럼 HashMap의 키 중복 불가 특성과 AbstractSet 클래스를 상속하는 방식을 조합하면, 자바에서 간단하면서도 효율적인 커스텀 HashSet을 구현할 수 있습니다.