김찬진의 개발 블로그

23/07/14 [Collection? Collections? Iterable? Iterator?] 본문

1일1배움/Java

23/07/14 [Collection? Collections? Iterable? Iterator?]

kim chan jin 2023. 1. 29. 18:14

Collection

- Collection 인터페이스는 자바의 컬렉션 프레임워크에서 모든 컬렉션 클래스의 상위 인터페이스로 사용되는 인터페이스입니다. Collection은 객체의 그룹을 나타내며, 컬렉션에 포함된 객체를 다루기 위한 공통된 작업을 정의합니다.
- 크기(Size) 관리:
    - size(): 컬렉션에 포함된 요소의 개수를 반환합니다.
    - isEmpty(): 컬렉션이 비어 있는지 여부를 확인합니다.
    - clear(): 컬렉션의 모든 요소를 제거합니다.
- 요소 추가 및 제거:
    - add(E element): 컬렉션에 요소를 추가합니다.
    - remove(Object object): 컬렉션에서 해당 요소를 제거합니다.
    - addAll(Collection<? extends E> collection): 다른 컬렉션의 모든 요소를 현재 컬렉션에 추가합니다.
    - removeAll(Collection<?> collection): 다른 컬렉션에 있는 요소들을 현재 컬렉션에서 제거합니다.
- 검색 및 포함 여부 확인:
    - contains(Object object): 컬렉션이 지정된 요소를 포함하고 있는지 여부를 확인합니다.
    - containsAll(Collection<?> collection): 컬렉션이 다른 컬렉션의 모든 요소를 포함하고 있는지 여부를 확인합니다.
    - iterator(): 컬렉션의 요소를 순회하기 위한 Iterator 객체를 반환합니다.
- 배열로 변환:
    - toArray(): 컬렉션의 요소를 배열로 변환합니다.
- 기타 유틸리티:
    - equals(Object object): 다른 객체와 현재 컬렉션이 동일한지 여부를 확인합니다.
    - hashCode(): 컬렉션의 해시 코드를 반환합니다.
    - toString(): 컬렉션의 문자열 표현을 반환합니다.
Collection 인터페이스는 다양한 하위 인터페이스와 클래스를 포함하는 상위 개념입니다. 예를 들어, List, Set, Queue 등의 인터페이스는 Collection 인터페이스를 확장하여 특정 유형의 컬렉션을 정의합니다. 따라서, Collection 인터페이스를 구현한 클래스는 컬렉션의 일반적인 동작과 기능을 제공하며, 다양한 유형의 컬렉션을 처리하는 데 사용됩니다.

 

Collections

- Collections 클래스는 자바의 java.util 패키지에 속하는 유틸리티 클래스입니다. 이 클래스는 컬렉션 객체를 조작하고 정렬하며, 검색 및 변환 등과 같은 다양한 기능을 제공합니다. Collections 클래스는 static 메서드들로 구성되어 있습니다
- 정렬(Sorting):
    - sort(): 컬렉션을 정렬합니다. 정렬 기준은 컬렉션 요소의 자연 순서 또는 사용자 정의된 Comparator를 사용할 수 있습니다.
    - reverseOrder(): 요소의 역순 정렬을 위한 Comparator를 반환합니다.
    - reverse(): 컬렉션 요소의 순서를 반대로 변경합니다.
-검색(Searching):
    - binarySearch(): 정렬된 컬렉션에서 이진 검색을 수행하여 요소를 찾습니다. 검색은 컬렉션이 사전에 정렬되어 있어야 합니다.
- 동기화(Synchronization):
    - synchronizedCollection(): 컬렉션을 스레드 안전하게 만들기 위해 동기화된(wrapper) 컬렉션을 반환합니다.
    - synchronizedList(), synchronizedSet(), synchronizedMap(): 특정 유형의 컬렉션을 동기화된(wrapper) 컬렉션으로 반환합니다.
- 변경 불가능한 컬렉션(Immutable Collections):
    - unmodifiableCollection(): 변경할 수 없는(wrapper) 컬렉션을 반환합니다.
    - unmodifiableList(), unmodifiableSet(), unmodifiableMap(): 변경할 수 없는(wrapper) 특정 유형의 컬렉션을 반환합니다.
- 컬렉션 생성 및 복사:
    - emptyList(), emptySet(), emptyMap(): 비어있는 읽기 전용(wrapper) 컬렉션을 반환합니다.
    - singletonList(), singleton(), singletonMap(): 단일 요소를 포함하는 읽기 전용(wrapper) 컬렉션을 반환합니다.
    - addAll(): 여러 요소를 기존 컬렉션에 추가합니다.
    - copy(): 요소를 하나의 컬렉션에서 다른 컬렉션으로 복사합니다.
기타 유틸리티:
    - frequency(): 컬렉션에서 주어진 요소의 발생 횟수를 계산합니다.
    - disjoint(): 두 개의 컬렉션이 공통 요소를 가지고 있는지 확인합니다.
    - max(), min(): 컬렉션에서 최대 또는 최소 요소를 찾습니다.
    - shuffle(): 컬렉션의 요소를 무작위로 섞습니다.

 

위의 기능은 Collections 클래스에서 제공하는 일부 메서드입니다. 이 외에도 다양한 유틸리티 메서드와 기능이 있으며, 컬렉션 객체를 보다 효율적이고 편리하게 다룰 수 있도록 도와줍니다.

 

Iterator

- 컬렉션 클래스들이 요소를 다루는 메서드들을 표준화한 인터페이스

- 컬렉션 클래스가 Itr객체를 반환하는 iterator() 메서드를 구현했다면, Itr 내부 클래스는 Iterator 인터페이스를 상속받아 해당 컬렉션 클래스의 성격에 따라 알맞게 hasNext(), next(), remove() 메서드들을 구현한다. (Itr 내부 클래스는 Iterator 인터페이스를 상속받았다.)

public interface Iterator {
    boolean hasNext();
    Object next();
    void remove();
}

 

Iterable

- 2가지 목적(메서드)이 존재

- iterator() : 컬렉션 클래스가 구현해야 할 메서드로서 존재함 (실제 컬렉션 클래스들은 Iterable 인터페이스를 상속하지도 않고 구현하진 않음. 이유는 맨 아래에)

- forEach() : Iterable 인터페이스는 컬렉션을 순회할 수 있는 객체를 나타냅니다. Iterable을 구현한 클래스는 foreach 루프와 같은 반복문에서 직접 사용될 수 있습니다. Iterable은 iterator() 메서드를 구현해야 하며, 이 메서드는 컬렉션의 요소를 반복 제공하는 Iterator 객체를 반환합니다.

public interface Iterable<T> {

    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
}

 

실제 컬렉션 클래스에서 Iterable 인터페이스, Iterator 인터페이스를 어떻게 사용할까?

Itr 내부 클래스에 주목!

 

 

ArrayList 일부 코드

public class ArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    // ...
    public Iterator<E> iterator() {
        return new Itr(); // ArrayList 객체의 요소에 접근하는 Iterator 객체 반환
    }
    
    private class Itr implements Iterator<E> {
        // hasNext(), next(), remove() 구현 내용 생략
    }
    // ...
}

- 컬렉션 클래스가 iterator() 메서드를 직접 구현한다. (Iterable 인터페이스를 상속받진 않는다!)

- 사실 iterator() 메서드 구현이라고 해봤자 Itr 객체를 생성하고 반환하는 것이다. (Itr 클래스는 Iterator 인터페이스를 상속받았다.)

- 컬렉션 클래스가 Itr객체를 반환하는 iterator() 메서드를 구현했다면, Itr 내부 클래스는 Iterator 인터페이스를 상속받아 해당 컬렉션 클래스의 성격에 따라 알맞게 hasNext(), next(), remove() 메서드들을 구현한다.

- 의문점과 GPT의 생각

더보기


컬렉션 클래스가 Iterable 인터페이스를 상속받지 않고 왜 직접 iterator() 메서드를 직접 구현한 것일까? Iterable 인터페이스를 상속받지 않는 한 강제력이 없지 않나? Iterable 인터페이스는 자바의 컬렉션 클래스에서만 활용될 인터페이스일 뿐이기 때문에 강제력이 없어도 문제가 없는 것인가? 그럼 애초에 Iterable 인터페이스를 만들 필요가 없지 않나?

GPT
Iterable 인터페이스와 iterator() 메서드를 직접 구현하는 이유는 자바 컬렉션 프레임워크의 일관성과 호환성을 유지하기 위해서입니다.
Iterable 인터페이스는 자바의 컬렉션 프레임워크에서 컬렉션을 순회하는 공통된 방법을 제공하기 위해 도입되었습니다. 이 인터페이스를 구현한 클래스는 foreach 루프를 포함한 다양한 컬렉션 관련 API에서 사용될 수 있습니다. Iterable 인터페이스를 구현함으로써 컬렉션 클래스는 컬렉션의 요소에 접근하는 데 일관된 방식을 제공하게 되며, 컬렉션 프레임워크의 유연성과 호환성을 보장합니다.
그러나 Iterable 인터페이스를 강제적으로 상속받도록 강요하는 것은 아닙니다. Iterable을 구현하지 않고도 직접 iterator() 메서드를 구현하는 이유는, 이전에 개발되었던 컬렉션 클래스들이 Iterable 인터페이스가 도입되기 전에 이미 존재했기 때문입니다. 이러한 클래스들은 기존 코드와의 호환성을 유지하기 위해 Iterable을 상속받지 않고 iterator() 메서드를 직접 구현합니다.
또한, Iterable 인터페이스는 자바의 컬렉션 클래스뿐만 아니라, 사용자 정의 컬렉션 클래스에서도 활용될 수 있습니다. 사용자는 Iterable 인터페이스를 구현하여 자신만의 컬렉션을 만들 수 있고, 이를 foreach 루프와 같은 컬렉션 관련 API에서 사용할 수 있습니다. 따라서 Iterable 인터페이스는 컬렉션 프레임워크의 확장성과 유연성을 높이는 데 도움을 줍니다.
결론적으로, Iterable 인터페이스와 iterator() 메서드의 존재는 컬렉션 프레임워크의 일관성과 호환성을 유지하기 위한 목적을 가지며, 이를 구현하지 않은 클래스에서는 기존 코드와의 호환성을 위해 iterator() 메서드를 직접 구현합니다. 또한, Iterable은 사용자 정의 컬렉션 클래스에서도 활용될 수 있는 유용한 인터페이스입니다.

Comments