김찬진의 개발 블로그

[23/07/17] Iterable, Iterator, generics wildcard 종합연습 본문

1일1배움/Java

[23/07/17] Iterable, Iterator, generics wildcard 종합연습

kim chan jin 2023. 7. 17. 13:42

상황 가정

- 커스텀 컬렉션 클래스 MyCollection 을 만들었다

- MyCollection 은 Iterable 인터페이스, Iterator 인터페이스를 상속받고 각 메서드들을 구현했다

    - Iterable 인터페이스 : iterator() (forEach(), spliterator() 는 default method이므로 오버라이딩X)

    - Iterator 인터페이스: hasNext(), next() (remove(), forEachRemaining() 는 default method이므로 오버라이딩X)

(커스텀 컬렉션 클래스이므로 Iterable 인터페이스를 상속받고 iterator() 메서드를 오버라이딩했다. 만약 옛날 컬렉션 클래스라면 Iterable 인터페이스를 상속받지 않고 직접 구현했을 것이다)

 

package java.lang;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;

public interface Iterable<T> {
    
    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) { // 와일드카드, super로 다형성 꾀함
        Objects.requireNonNull(action);
        for (T t : this) { // this: Iterable 인터페이스를 상속받은 컬렉션 클래스(조상 클래스 포함)를 의미
            action.accept(t);
        }
    }

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

 

package generics;

import java.util.Iterator;
import java.util.function.Consumer;

class Fruit {
    private String name;

    public Fruit(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

class Apple extends Fruit {
    private String color;

    public Apple(String name, String color) {
        super(name);
        this.color = color;
    }

    public String getColor() {
        return color;
    }
}

class MyCollection<T> implements Iterable<T> {
    private T[] elements;
    private int size;

    public MyCollection(int capacity) {
        elements = (T[]) new Object[capacity];
        size = 0;
    }

    public void add(T element) {
        if (size < elements.length) {
            elements[size] = element;
            size++;
        }
    }

    @Override
    public Iterator<T> iterator() {
        return new MyIterator();
    }

    private class MyIterator implements Iterator<T> {
        private int currentIndex;

        public MyIterator() {
            currentIndex = 0;
        }

        @Override
        public boolean hasNext() {
            return currentIndex < size;
        }

        @Override
        public T next() {
            T element = elements[currentIndex];
            currentIndex++;
            return element;
        }
    }
}

public class GTest3 {
    public static void main(String[] args) {
        MyCollection<Apple> apples = new MyCollection<>(3);
        apples.add(new Apple("Apple 1", "Red"));
        apples.add(new Apple("Apple 2", "Green"));

        Consumer<Object> objectConsumer = object -> {
            System.out.println("Object: " + object);
        };
        // Consumer<Object> objectConsumer1 = new Consumer<Object>() {
        //     @Override
        //     public void accept(Object object) {
        //         System.out.println("Object: " + object);
        //     }
        // }
        Consumer<Fruit> fruitConsumer = fruit -> {
            System.out.println("Fruit: " + fruit.getName());
            // System.out.println("Fruit: " + fruit.getColor());
        };
        Consumer<Apple> appleConsumer = apple -> {
            System.out.println("Apple Name: " + apple.getName());
            System.out.println("Apple Color: " + apple.getColor());
        };

        apples.forEach(objectConsumer); // Object 타입으로 처리
        apples.forEach(fruitConsumer); // Fruit 타입으로 처리
        apples.forEach(appleConsumer); // Apple 타입으로 처리
        // 이 모든 것은 forEach(Consumer<? super T> action) {...} 덕분

    }
}
Comments