Algorithm/자료구조 개념

[자료구조] 자바의 자료구조(Collection) - 1

지구우중 2024. 1. 4. 22:20

자료구조 란?

자료구조: 데이터를 효율적으로 구조화하고 저장하는 방법을 다루는 구조. 데이터를 적절한 형태로 조직화하여 효과적으로 처리할 수 있도록 돕는 구조와 알고리즘의 집합을 의미한다. 프로그램이 데이터를 적절하게 저장하고 검색하며, 데이터 간의 관계를 관리하는 데에 중요한 역할을 한다.

 

자료 구조에는 다양한 유형이 있으며, 선택한 자료구조에 따라 프로그램의 성능이 크게 영향을 받을 수 있다. 몇 가지 흔히 사용되는 자료구조에는 배열, 연결 리스트, 스택, 큐, 트리, 그래프 등이 포함된다. 이러한 자료구조들은 각각 특정한 작업이나 문제 해결에 효과적인 도구로 사용될 수 있다.

 

C++의 STL과 같이 자바에서도 데이터를 저장하는 자료구조들을 한 곳에 모아 편리하게 관리하고 사용하도록 제공한다. 이를 Java Collection Framework라 부른다.

 

Java Collection Framework

Java Collection Framework: 흔히 컬렉션이라 부르는 Java Collection Framework는 자바에서 데이터를 저장, 관리 및 처리하기 위해 표준화된 방법을 제공하는 라이브러리이다. 이 프레임워크는 데이터를 구조화하고 조작하기 위한 다양한 인터페이스와 클래스를 제공하여 프로그래머가 효율적으로 작업할 수 있도록 돕는다.

 

자바의 Collection은 위의 그림과 같이 계층적인 구조로 이루어져 있다. 이 계층은 인터페이스를 통해 구현된다. 또한 기본 데이터 타입(원시 데이터 타입)이 아닌, 참조 데이터 타입만 저장이 가능하다. 때문에  기본 데이터 타입을 객체로 감싸는 Wrapper 클래스를 사용하거나, Java 5 이후 버전부터는 AutoBoxing을 통해 자동으로 Wrapper 클래스로 변환할 수 있다.

 

List<Integer> list = new ArrayList<>();

list.add(1); // AutoBoxing 원시 타입 1을 Integer 객체로 자동으로 변환하여 리스트에 추가
list.add(2);

int value = list.get(0); // unboxing Integer객체를 원시 타입인 int로 자동 변환
AutoBoxing: 기본 데이터 타입이 Wrapper 클래스의 타입의 파라미터를 받는 메서드를 통과할 때, 기본 데이터 타입이 Wrapper 클래스의 변수로 할당될 때 자바의 컴파일러가 자동으로 Wrapper 클래스의 객체로 바꾸는 과정을 의미한다. 이와 반대되는 과정을 unBoxing이라 부른다. 이를 통해 명시적으로 타입 캐스팅을 수행하지 않아도 된다.

 

Iterator

Iterator: 컬렉션을 순회하면서 각 요소에 접근할 수 있도록 하는 인터페이스. 연속적인 요소에 대한 반복 호출이 가능한 반복자. Iterable 인터페이스가 해당 객체를 가지고 있다.

jdk1.2부터 컬렉션 개념이 도입되면서, Iterator 인터페이스가 함께 등장했다. Colleaction 인터페이스가 Iterable 인터페이스를 상속받고 Iterable 인터페이스는 Iterator를 반환하는 iterator() 메서드를 가지고 있기 때문에 Collection 인터페이스를 구현 및 상속한 모든 컬렉션 클래스에서 사용 가능하다.

 

Iterator의 메서드

public interface Iterator<E> {
    boolean hasNext();
    E next();
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

 

  • hasNext()
    • 다음 요소가 있는지 여부를 확인하는 메서드. 요소가 있다면 true를 반한하고, 더이상 요소가 없다면 'false'를 반환한다.
  • next()
    • 다음 요소를 반환하는 메서드. 'hasNext()'로 확인한 후에 호출해야 한다(요소가 더이상 존재하지 않다면, NoSuchElementException이 발생함) 반환 타입은 제너릭으로 선언되어 있어, 실제 컬렉션에 저장된 요소의 타입과 일치하다.
  • remove()
    • 컬렉션에서 현재 요소를 제거하는 기능을 제공한다. 이 메서드는 반드시 'Iterator'를 통해서만 호출되어야 하며, 일부 컬렉션에서는 이 메서드를 지원하지 않을 수 있다. 만약 지원되지 않다면 UnsupportedOperationException을 던진다.
  • forEachRemaining() 
    • 남은 모든 요소에 대해 주어진 동작(Consumer로 표현된 함수)을 수행한다. 이는 Java 8에서 추가된 디폴트 메서드이다.

일반적으로 while 루프와 hasNext(), next() 메서드를 사용하여 컬렉션의 요소를 순회한다.

List<String> list = Arrays.asList("Apple", "Banana", "Orange");

Iterator<String> iterator = list.iterator();

while (iterator.hasNext()) {
    String element = iterator.next();
    System.out.println(element);
}

// 이 다음부터 iterator객체는 사용 불가능
한 번 사용된 Iterator 객체는 재사용이 불가능하다.

 

Iterable

Iterable: 이 인터페이스는 객체가 "반복 가능"한 것임을 나타낸다. Iterable은 향상된 for 루프 등을 사용하여 컬렉션을 순회하는 데 활용되고, Iterator는 직접적으로 컬렉션을 순회하는 데 사용된다. Collection 인터페이스가 상속하고 있는 인터페이스이다. 

 

public interface Iterable<T> {

    Iterator<T> iterator();

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

    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

 

 

  • iterator()
    • 컬렉션의 요소를 반복하는 데 사용되는 Iterator를 반환한다.
  • forEach()
    • 모든 요소에 대해 주어진 동작을 수행한다. 이 메서드는 Java 8에서 추가되었으며, 향상된 for 루프를 사용하지 않고도 간편하게 모든 요소에 대한 동작을 수행할 수 있다.
  • spliterator()
    • 컬렉션의 요소를 병렬로 처리할 수 있도록 하는 Spliterator를 반환한다. Java 8에서 추가된 것으로, 병렬 프로그래밍에서 활용된다.
List<String> list = new ArrayList<>(List.of("Apple", "Banana", "Orange"));

list.forEach(System.out::println);
list.spliterator().forEachRemaining(System.out::println);

 

 

Collection

Collection: Collection 인터페이스는 Java의 컬렉션 프레임워크에서 모든 컬렉션 클래스가 구현해야 하는 기본적인 동작을 정의한 인터페이스이다. Collection 인터페이스는 Iterable 인터페이스를 상속받고 있다.

 

public interface Collection<E> extends Iterable<E> {
    int size();

    boolean isEmpty();

    boolean contains(Object o);

    Iterator<E> iterator();

    Object[] toArray();

    <T> T[] toArray(T[] a);

    default <T> T[] toArray(IntFunction<T[]> generator) {
        return toArray(generator.apply(0));
    }

    boolean add(E e);

    boolean remove(Object o);

    boolean containsAll(Collection<?> c);

    boolean addAll(Collection<? extends E> c);

    boolean removeAll(Collection<?> c);

    default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }

    boolean retainAll(Collection<?> c);

    void clear();

    int hashCode();

    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }

    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }

    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
}
  • size()
    • 컬렉션에 포함된 요소의 개수를 반환한다.
  • isEmpty()
    • 컬렉션이 비어있는지 여부를 확인한다.
  • contains()
    • 지정된 요소가 컬렉션에 포함되어 있는지 여부를 확인한다.
  • iterator()
    • 컬렉션의 요소를 순회하는 데 사용되는 반복자를 반환한다.
  • toArray()
    • 컬렉션의 모든 요소를 배열로 반환한다.
  • add()
    • 지정된 요소를 컬렉션에 추가한다.
  • remove()
    • 지정된 요소를 컬렉션에서 제거한다.
  • containsAll()
    • 지정된 컬렉션의 모든 요소가 현재 컬렉션에 포함되어 있는지 여부를 확인한다.
  • addAll()
    • 지정된 컬렉션의 모든 요소를 현재 컬렉션에 추가한다.
  • removeAll()
    • 지정된 컬렉션에 포함된 모든 요소를 현재 컬렉션에서 제거한다.
  • retainAll()
    • 지정된 컬렉션에 포함된 요소 이외의 모든 요소를 현재 컬렉션에서 제거한다.
  • clear()
    • 컬렉션의 모든 요소를 제거한다.
  • equals()
    • 지정된 객체와 현재 컬렉션이 같은지 여부를 확인한다.
  • hashCode()
    • 컬렉션의 해시 코드를 반환한다.
  • spliterator()
    • 컬렉션의 요소를 병렬로 처리할 수 있도록 하는 Spliterator를 반환한다.
  • stream()
    • 컬렉션을 스트림으로 변환하여 스트림 연산을 수행할 수 있도록 한다.
  • parallelStream()
    • 컬렉션을 병렬 스트림으로 변환하여 병렬 스트림 연산을 수행할 수 있도록 한다.