사용자 정의 컬렉션 구현: 효율적인 데이터 관리

 

자바 컬렉션 프레임워크는 다양한 데이터 구조를 제공하지만,

특정 요구사항을 충족시키기 위해 사용자 정의 컬렉션을 구현해야 할 때가 있습니다.

이 글에서는 사용자 정의 컬렉션을 구현하는 방법과 모범 사례를 알아보겠습니다.

사용자 정의 컬렉션이 필요한 이유

이유 설명
특수 기능 추가 기본 컬렉션이 제공하지 않는 특수 기능이나 동작 필요 시
성능 최적화 특정 사용 사례에 맞게 성능 개선 필요 시
도메인 제약 조건 비즈니스 로직이나 도메인 제약 조건을 컬렉션에 적용할 때
영속성 구현 메모리가 아닌 다른 저장소(파일, DB 등)에 데이터 유지 필요 시

사용자 정의 컬렉션 구현 방법

1. 추상 구현 클래스 활용

자바는 사용자 정의 컬렉션 구현을 쉽게 하기 위해 다음과 같은 추상 구현 클래스를 제공합니다.

추상 클래스 용도 최소 구현 메서드
AbstractCollection Set이나 List가 아닌 컬렉션 iterator(), size()
AbstractSet Set 구현 AbstractCollection과 동일
AbstractList 랜덤 액세스 기반 List get(int), size()
AbstractSequentialList 순차 액세스 기반 List listIterator(), size()
AbstractMap Map 구현 entrySet()

2. 구현 과정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 배열 기반 사용자 정의 리스트 예제
public class MyArrayList<T> extends AbstractList<T> {
    private final T[] a;
    public MyArrayList(T[] array) {
        a = array;
    }
    @Override
    public T get(int index) {
        return a[index];
    }
    @Override
    public T set(int index, T element) {
        T oldValue = a[index];
        a[index] = element;
        return oldValue;
    }
    @Override
    public int size() {
        return a.length;
    }
}
// 사용 예
List<String> myList = new MyArrayList<>(new String[]{“A”“B”“C”});
cs

 

3. Iterable 인터페이스 구현

for-each 루프를 사용할 수 있는 컬렉션을 만들려면 Iterable 인터페이스를 구현해야 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class CustomCollectionWrapper implements Iterable<String>, Iterator<String> {
    private HashMap<String, Object> internalStorage = new HashMap<>();
    private int count = 0;
    public void add(String key, Object value) {
        internalStorage.put(key, value);
    }
    public Object get(String key) {
        return internalStorage.get(key);
    }
    @Override
    public boolean hasNext() {
        if (count < internalStorage.size()) {
            return true;
        }
        return false;
    }
    // Iterator 메서드 구현
    // …
}
cs

사용자 정의 컬렉션 구현 예제

1. 커스텀 배열 컬렉션

다음은 동적으로 크기가 조정되는 배열 기반 컬렉션 예제입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class CustomArrayCollection {
    private Object[] elements;
    private int countElements = 0;
    // 기본 생성자 – 초기 용량 10
    public CustomArrayCollection() {
        elements = new Object[10];
        countElements = 0;
    }
    // 요소 추가
    public void add(Object element) {
        // 용량 확인 및 필요시 확장
        if (countElements == elements.length) {
            // 용량 두 배로 증가
            int newCapacity = elements.length * 2;
            Object[] newArray = new Object[newCapacity];
            System.arraycopy(elements, 0, newArray, 0, elements.length);
            elements = newArray;
        }
        elements[countElements++= element;
    }
    // 크기 반환
    public int size() {
        return countElements;
    }
    // 요소 가져오기
    public Object get(int index) {
        if (index >= countElements) {
            throw new IndexOutOfBoundsException();
        }
        return elements[index];
    }
}
cs

 

2. 특수 목적 컬렉션 예제

특정 도메인 객체를 관리하는 컬렉션 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class BaseballCardCollection {
    private BaseballCard[] baseballCardList;
    private int size;
    public BaseballCardCollection() {
        baseballCardList = new BaseballCard[10];
        size = 0;
    }
    public int size() {
        return size;
    }
    public void addCard(BaseballCard card) {
        if (size == baseballCardList.length) {
            // 배열 크기 확장
            BaseballCard[] newArray = new BaseballCard[baseballCardList.length * 2];
            System.arraycopy(baseballCardList, 0, newArray, 0, baseballCardList.length);
            baseballCardList = newArray;
        }
        baseballCardList[size++= card;
    }
    public boolean removeCard(BaseballCard card) {
        for (int i = 0; i < size; i++) {
            if (baseballCardList[i].equals(card)) {
                // 카드 제거 및 배열 재정렬
                System.arraycopy(baseballCardList, i + 1, baseballCardList, i, size  i  1);
                baseballCardList[size] = null;
                return true;
            }
        }
        return false;
    }
}
cs

 

모범 사례

  1. equals()와 hashCode() 재정의: 사용자 정의 객체를 컬렉션에 저장할 때는 이 메서드들을 올바르게 구현해야 합니다.

  2. 성능 고려: 자주 사용되는 연산에 대해 최적화된 구현을 제공하세요.

  3. 테스트: 구현한 컬렉션이 예상대로 동작하는지 철저히 테스트하세요.

  4. 문서화: 컬렉션의 동작과 제약 조건을 명확히 문서화하세요.

사용자 정의 컬렉션을 구현함으로써 애플리케이션의 특정 요구사항에 맞는 데이터 구조를 만들 수 있으며,

이는 코드의 가독성과 성능을 향상시키는 데 도움이 됩니다.

 

 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다