Collection과 Iterator

2022. 10. 20. 19:47JAVA

컬렉션이란

여러 데이터의 묶음을 말한다.

기본적으로 Collection은 추상체이며, 구현체의 종류로는 List, Set, Map 등이 있겠다.
List, Set, Map의 구현체로는 LinkedList, HashSet, HashMap, Vector, Stack 등 자주 사용하는 자료구조가 이에 해당한다.

이번 포스팅에서는 MyCollection이라는 나만의 Collection 클래스를 정의하면서 Java의 컬렉션에 대해 알아보자.


MyCollection

데이터의 묶음답게, MyCollection 클래스는 지네릭스를 이용해 어떤 타입이든 사용 가능하도록 하였다. 

public class MyCollection <T>{
    private List<T> list;

    public MyCollection(List<T> list) {
        this.list = list;
    }
}

현재로는 MyCollection 클래스를 생성해도 데이터를 조작할 수 있는 메소드가 하나도 없는 상태다.
만약 MyCollection에 저장된 요소들을 하나하나씩 사용하고 싶다면, 우리가 직접 for문으로 MyCollection을 순회하며 저장된 요소들을 꺼내서 사용해야 한다.

객체지향의 장점을 살려서, 우리가 직접 코드를 작성하기보다 MyCollection 클래스에 메소드로 생성해놓는다면 직접 for문을 작성할 필요가 없어진다. 

그럼 클래스에 forEach(), map() 메소드를 추가해보자.

public void forEach(Consumer<T> consumer) {
        for (int i = 0; i < list.size(); i++) {
            T data = list.get(i);
            consumer.accept(data);
        }
    }

    public <U> MyCollection<U> map(Function<T, U> function) {
        List<U> newList = new ArrayList<>();
        forEach(data -> newList.add(function.apply(data)));

        return new MyCollection<>(newList);
    }

map() 메소드는 타입을 변환해주는 함수라고 생각하면 쉽다.

아래는 forEach(), map() 메소드의 용례다.

public class Main {
    public static void main(String[] args) {
        new MyCollection<>(Arrays.asList(1, 2, 3, 4, 5))
                .forEach(i -> System.out.println(i));  // 콘솔에 1 2 3 4 5

        MyCollection<String> c1 = new MyCollection<>(Arrays.asList("A", "CD", "BCD", "DFEG", "EFGHI"));
        MyCollection<Integer> c2 = c1.map(s -> s.length()); // (String -> Integer)

        c1.forEach(s -> System.out.println(s)); // 콘솔에 A CD BCD DFEG EFGHI 출력
        c2.forEach(i -> System.out.println(i)); // 콘솔에 1 2 3 4 5 출력  

    }
}

직접 구현한 map() 메소드를 이용해 String -> Integer로 변환이 가능하다.

이번에는 데이터들 중 필요한 것만 걸러내는 filter() 메소드와 MyCollection에 저장된 데이터의 수를 반환하는 size() 메소드를 만들어보면 다음과 같다.

    public MyCollection<T> filter(Predicate<T> predicate) {
        List<T> newList = new ArrayList<>();
        forEach(data -> {
            if(predicate.test(data))
                newList.add(data);
        });

        return new MyCollection<>(newList);
    }

    public int size() {
        return list.size();
    }

용례

public class Main {
    public static void main(String[] args) {
        new MyCollection<>(Arrays.asList(1, 2, 3, 4, 5))
                .forEach(i -> System.out.println(i));

        MyCollection<String> c1 = new MyCollection<>(Arrays.asList("A", "CD", "BCD", "DFEG", "EFGHI"));
        MyCollection<Integer> c2 = c1.map(s -> s.length());

        c1.forEach(s -> System.out.println(s));
        c2.forEach(i -> System.out.println(i));


        MyCollection<String> c3 = c1.filter(s -> s.length() % 2 == 0); 
        c3.forEach(s -> System.out.println(s)); // 콘솔에 CD DFEG가 출력된다. 
    }
}

isEmpty, indexOf, contains 메소드는 아래와 같이 작성해봤다. 

    public boolean isEmpty(){
        return list.size() == 0;
    }

    public int indexOf(T value) {
        int r = 0;

        for (int i = 0; i < list.size(); i++) {
            if(list.get(i).equals(value)) return i;
        }

        return -1;
    }

    public boolean contains(T value) {
        if (list.indexOf(value) >= 0) {
            return true;
        }

        return false;
    }

Iterator

여러 데이터의 묶음을 하나씩 처리할 수 있는 도구

public class Main3 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("A", "CD", "BCD", "DFEG", "EFGHI");
        Iterator<String> iter = list.iterator();  //iterator 획득
        iter.next(); // A
        iter.next(); // CD
        iter.next(); // BCD
        System.out.println(iter.next()); // DFEG
        
        while (iter.hasNext()) {
            System.out.println(iter.next()); // EFGHI
        }
    }
}

왜 콘솔에서 위의 결과가 나왔냐면, Iterator는 커서와 비슷해서
next()를 호출하면 다음 대상으로 커서가 이동하기 때문이다. 
만약 마지막 데이터에서 next()를 호출한 다음 출력하려고 하면 exception이 발생하므로,
while문과 함께 사용하는 것이 일반적이다.

'JAVA' 카테고리의 다른 글

Java - Calculator 과제 회고  (0) 2022.10.30
Java 숫자야구  (0) 2022.10.21
JAVA 인터페이스 기능과 디폴트 메소드(Default Method)  (0) 2022.10.20
Java equals()와 hashCode()  (0) 2022.10.19
Optional<T>  (0) 2022.02.16