Java Collection Framework

전홍영·2024년 6월 12일
0

Java

목록 보기
13/15

Java의 Collection Framework는 데이터 구조와 알고리즘을 효율적으로 구현하고 사용할 수 있게 해주는 클래스를 모은 라이브러리이다. 컬랙션 프레임워크는 굉장히 많이 사용이 되는데 컬렉션 프레임워크의 맨 상위 에 있는 인터페이스를 기반으로 이를 구현한 클래스들로 구성되어 있다.

구성 요소

Collection Interface

가장 상위 인터페이스로, 모든 컬렉션 클래스들이 구현해야 하는 기본적인 메서드를 정의한다. 주요 메서드로는 add(), remove(), size(), clear() 등이 존재한다.

List

컬렉션 프레임 워크는 크게 3가지의 인터페이스로 나눌 수 있다. 그 중 하나가 List이다. 리스트의 특징은 순서가 있고 중복 요소를 허용한다는 점이다. 또한 인덱스를 통해서 요소에 접근이 가능하기 때문에 빠른 접근이 가능하다. 배열과는 다르게 크기가 지정된 것이 아닌 동적으로 크기가 변경되는 특징이 있다.

구현 클래스

ArrayList

내부적으로 배열을 사용하여 요소를 저장하는 클래스이다. 요소에 랜덤 접근이 빠르며, 삽입/삭제가 배열의 크기 조정이 필요할 경우 느릴 수 있다.

@Test
void ArrayList() {
    ArrayList<Object> list = new ArrayList<>();

    for (int i = 0; i < 10; i++) {
        list.add(i);
    }

    ArrayList<Object> list2 = new java.util.ArrayList<>(list);

    assertThat(list).isEqualTo(list2);// success
}

LinkedList

연결 리스트는 삽입과 삭제가 빠르지만 랜덤 접근이 느린 리스트이다. 연결리스트는 큐와 덱 인터페이스도 구현하고 있어 리스트 뿐만 아니라 스택이나 큐,덱 같은 다양한 자료구조에 활용될 수 있다.

@Test
void linkedList() {
    LinkedList<Object> list = new LinkedList<>();

    for (int i = 0; i < 10; i++) {
        list.add(i);
    }

    LinkedList<Object> list2 = new LinkedList<>(list);

    assertThat(list).isEqualTo(list2);
}

@Test
void linkedListQueue() {
    LinkedList<Object> list = new LinkedList<>();

    for (int i = 0; i < 10; i++) {
        list.offer(i);
    }

    for (int i = 0; i < 10; i++) {
        assertThat(list.poll()).isEqualTo(i);
    }
}

@Test
void linkedListStack() {
    LinkedList<Object> list = new LinkedList<>();

    for (int i = 0; i < 10; i++) {
        list.push(i);
    }

    for (int i = 0; i < 10; i++) {
        assertThat(list.pop()).isEqualTo(9 - i);
    }
}

@Test
void linkedListDeque() {
    LinkedList<Object> list = new LinkedList<>();

    for (int i = 0; i < 10; i++) {
        list.offerFirst(i);
    }

    for (int i = 0; i < 10; i++) {
        assertThat(list.pollFirst()).isEqualTo(9 - i);
    }
}

Map

Map은 키-값 싸으로 데이터를 저장하는 컬렉션을 일컫는다. 키는 중복될 수 있으나, 값은 중복될 수 없다는 특징이 있다.

구현 클래스

HashMap

HashMap은 키와 값의 순서를 보장하지 않는 해시 테이블을 기반으로 구현되어있는 Map이다. HashMap은 동기화되지 않아서 멀티스레드 환경에서는 사용하기에 부적절할 수 있다.

@Test
void hashMap() {
    HashMap<Object, Object> map = new HashMap<>();

    for (int i = 0; i < 10; i++) {
        map.put(i, i);
    }

    HashMap<Object, Object> map2 = new HashMap<>();

    for (int i = 0; i < 10; i++) {
        map2.put(i, i);
    }

    assertThat(map).isEqualTo(map2);
}

LinkedHashMap

HashMap가 유사하지만 LinkedHashMap은 입력된 순서를 유지한다는 특징이 있다.

TreeMap

이진 검색 트리를 기반으로 구현되며, 키를 정렬된 순서로 저장합니다.

@Test
void treeMap() {
    TreeMap<Object, Object> map = new TreeMap<>();

    for (int i = 10; i > 0; i--) {
        map.put(i, i);
    }

    map.forEach((k, v) -> System.out.println(k + " : " + v));
}

ConcurrentMap (ConcurrentHashMap)

ConcurrentMap은 멀티스레드 환경에서도 안전하게 사용할 수 있는 맵을 제공한다. 이는 기본적인 인터페이스를 확장하여 여러 스레드가 동시에 접ㄱ느하고 수정할 수 있는 환경에서도 데이터의 일관성을 유지하도록 설계되었다.

특징으로는 동시성을 보장하기 위해 여러 스레드가 접근하거나 수정할 때 발생할 수 있는 문제를 방지하기 위한 동기화 매커니즘이 내장되어 있다. 또한 원자적 연산을 제공하여 putIfAbsent(), remove(), replace() 등의 메서드는 단일 연산으로 취급되어, 중간에 다른 스레드가 개입할 수 없도록 한다.

Set

set은 집합이라고 생각하면 될 것 같다. 중복 요소를 허용하지 않는 컬렉션으로 순서가 보장되지 않을 수 있다. TreeSet을 제외하고 대부분의 Set 구현체에서는 null을 허용한다.

구현 클래스

HashSet, LinkedHashSet

가장 일반적으로 사용되는 Set 구현체로 내부적으로 해시 테이블을 사용하여 원소를 저장한다. LinkedHashSet은 입력 순서를 유지하지만 HashSet은 순서를 보장하지 않는다. HashSet은 빠른 삽입, 삭제, 조회 작업을 제공한다.

@Test
void hashSet() {
    HashSet<Object> set = new HashSet<>();

    for (int i = 0; i < 10; i++) {
        set.add(i);
    }

    HashSet<Object> set2 = new HashSet<>();

    for (int i = 0; i < 10; i++) {
        set2.add(i);
    }

    Assertions.assertThat(set).isEqualTo(set2);
}

@Test
void linkedHashSet() {
    LinkedHashSet<Object> set = new LinkedHashSet<>();

    for (int i = 0; i < 10; i++) {
        set.add(i);
    }

    LinkedHashSet<Object> set2 = new LinkedHashSet<>();

    for (int i = 0; i < 10; i++) {
        set2.add(i);
    }

    Assertions.assertThat(set).isEqualTo(set2);
}

TreeSet

NabigableSet 인터페이스를 구현하며, 내부적으로 이진 탐색 트리(레드-블랙 트리)를 사용하여 원소를 저장ㅎ나다. 원소들이 자연순서(오름차순) 또는 제공된 비교자(Comparator)에 따라 정렬된다. 다만, null을 허용하지 않는 구현체이다.

@Test
void treeSet() {
    TreeSet<Object> set = new TreeSet<>((o1, o2) -> o2.hashCode() - o1.hashCode());//비교자 추가

    for (int i = 0; i < 10; i++) {
        set.add(i);
    }

    set.iterator().forEachRemaining(System.out::println);//역순 출력
}

이렇듯 컬렉션 프레임워크는 다양한 자료구조를 제공하여 상황에 맞게 사용할 수 있도록 java에서 제공하는 라이브러리이다. 이를 사용하게 된다면 고성능의 데이터 구조와 알고리즘을 사용할 수 있고 일관된 인터페이스를 통해 코드를 이해하기 쉽고 유지보수하기가 좋아지게 된다. 따라서 직접 자료구조를 구현하기 보다는 컬렉션을 이용하여 구현한다면 다양한 이점을 사용할 수 있게되는 것이다.

profile
Don't watch the clock; do what it does. Keep going.

0개의 댓글