티스토리 뷰

Java의 정석_기초편

Iterator

DJDU 2022. 11. 3. 01:26

Iterator, ListIterator, Enumeration

  • 컬렉션에 저장된 데이터를 접근하는데 사용되는 인터페이스(읽어오기)
  • Enumeration은 Iterator의 구버젼(Iterator만 알면 된다)
  • ListIterator는 Iterator의 접근성을 향상시킨 것(단방향 ➝ 양방향)
더보기

Iterator인터페이스의 메서드

표11-12 Iterator인터페이스의 메서드

 

Iterator

  • 컬렉션에 저장된 요소들을 읽어오는 방법을 표준화한 것
  • 컬렉션에 iterator()를 호출해서 Iterator를 구현한 객체를 얻어서 사용
더보기

컬렉션에 저장된 요소들을 읽어오는 방법을 표준화한 것

  1. 확인 - hasNext()
  2. 읽기 - next()

'구조'(List, Set, Map)가 어떻게 되어있든간에, 있는지 '확인'(hasNext())하고 '읽기'(next())만 쓰면 된다. ⭐️

 

컬렉션에 iterator()를 호출해서 Iterator를 구현한 객체를 얻어서 사용

 

예제 11-5 ⭐️ ⭐️ ⭐️ ⭐️ ⭐️

더보기

1. iterator는 1회용이라 다 쓰고 나면 다시 얻어와야 한다.

2. iterator 대신 for문으로 바꿔보자.

실행결과는 전과 같습니다.

2. ArrayList 대신 HashSet으로 바꿔보자.

HashSet도 Collection의 자손이다. 따라서 iterator를 쓸 수 있다.

하지만, HashSet은 get메서드를 쓸 수 없다.

Collection 프레임웍을 사용하다보면 성능 등의 문제로 다른 컬렉션으로 변경해야 할 때가 있다.

그럴 때 ArrayList -> HashSet으로 바꿨을 때, HashSet에는 get()이 없기 때문에 에러가 난다.

Cannot resolve method 'get' in 'HashSet'

하지만, Iterator를 이용해서 요소를 가져오도록 했다면, '표준화'되어있기 때문에 Collection클래스가 바뀌어도 코드를 건드리지 않아도 된다. 이건 굉장한 장점이다.

코드는 계속 변하지만, 변경을 최소화하는 코드를 작성해야 한다.

Collection마다 구조가 다른데, 그것을 어떻게 가져와야 할지 우리가 신경쓰지 않아도 된다. 

 

3. Collection c 조상 타입 참조변수로 바꿔보자.

HashSet클래스는 set인터페이스를 구현했고, set인터페이스는 Collection인터페이스의 자손이다. 

다형성이 성립하기 때문에 이렇게 참조변수를 변경할 수 있다.

public class IteratorEx1 {
    public static void main(String[] args) {  // set은 Collection의 자손
        Collection c = new HashSet();

- IDE: IntelliJ > 참조변수 c 우클릭 > Refactor > Rename... > c 입력 후 ↵

public class IteratorEx1 {
    public static void main(String[] args) {  // set은 Collection의 자손
        Collection c = new HashSet();
        c.add("1");
        c.add("2");
        c.add("3");
        c.add("4");
        c.add("5");

        Iterator it = c.iterator();

        while(it.hasNext()) {
            Object obj = it.next();
            System.out.println(obj);
        }

        // iterator는 1회용이라 다 쓰고 나면 다시 얻와야 한다.
        it = c.iterator();  // 새로운 iterator객체를 얻는다.

        for (int i = 0; i < c.size(); i++) {
            Object obj = c.get(i);
            System.out.println(obj);
        }
    }
}

모든 참조변수 list가 c로 '자동변경'되었다.

 

참조변수 타입을 HashSet으로 일치시켜도 되지만, 나중에 TreeSet으로 타입을 바꾼다고 가정했을 때, 아래 코드를 모두 검토해야 한다. 클래스가 바뀌었기 때문이다. 하지만, 참조변수는 바뀌지 않았다. 

public class IteratorEx1 {
    public static void main(String[] args) {  // set은 Collection의 자손
        Collection c = new TreeSet();
//      Collection c = new HashSet();

 클래스를 HashSet에서 TreeSet으로 바꿔도, 참조변수는 바꾸지 않아도 된다. 

 이렇게 실제 구현 클래스가 달라도, 사용하는 멤버의 갯수는 동일하다. Collection인터페이스에 정의된 메서드만 사용했기 때문이다. 다른 걸 쓸 수 없다. 리모컨이 Collection이기 때문에 여기에 있는 것만 사용할 수 있다.

 

따라서 클래스가 바뀌었어도 아래에 코드들을 검토할 필요가 없다.

아래 코드에서는 두 클래스의 공통되는 멤버만 사용했을 것이기 때문이다. 

public class IteratorEx1 {
    public static void main(String[] args) {  // set은 Collection의 자손
        TreeSet c = new TreeSet();
//      HashSet c = new HashSet();

그런데 처음부터 참조변수의 타입을 TreeSet, HashSet으로 해놨다면, 클래스를 바꿨을 때 아래 코드들을 전부 검토해야 한다. 

HashSet에서 TreeSet으로 바꿨을 때, 아래 코드에서 HashSet에는 있지만, TreeSet에는 없는 메서드를 사용했을 수 있다.

 

물론, IDE가 컴파일 에러를 잡아주긴 한다. 하지만 처음부터 참조변수의 타입을 조상 인터페이스인 Collection으로 했다면, 어떤 클래스로 바꿔도 아래 코드를 검토할 필요가 없다. 아래에는 Collection인터페이스에 정의된 메서드 이외에는 사용하지 않았을 것이라는 확신이 있기 때문이다. 그래서 참조변수의 종류도 잘 결정해야 한다. 참조변수 타입과 객체 타입을 일치시킬 필요는 없다. 위와 같이 작성하는 것이 보다 유연한 코드이다.

 

Map과 Iterator

  • Map에는 iterator()가 없다.(Map은 Collection의 자손이 아님)
  • keySet(), entrySet(), values()를 호출(해서 Set 또는 Collection을 얻은 다음 거기에 iterator()를 호출할 수 있다.)
더보기

Map에는 iterator()가 없다

  • Map은 Collection의 자손이 아니기 때문
  • 그렇다면 Map에 저장된 요소들을 가져오려면 어떻게 해야 할까?

keySet(), entrySet(), values()를 호출해야

    Map map = new HashMap();
        ...
//  Set eSet = map.entrySet();
//  Iterator it = eSet.iterator();  // 아래 한 줄과 위 두 둘은 같은 코드이다.
    Iterator it = map.entrySet().iterator();

방법

① map.entrySet()의 실행결과가 Set이므로

    Iterator it = map.entrySet().iterator();
→   Iterator it = Set인스턴스.iterator();

② map.entrySet()를 통해 얻은 Set인스턴스의 iterator()를 호출해서 Iterator인스턴스를 얻는다.

    Iterator it = Set인스턴스.iterator();
→   Iterator it = Iterator인스턴스;

③ 마지막으로 Iterator인스턴스의 참조가 it에 저장된다.

'Java의 정석_기초편' 카테고리의 다른 글

Comparator와 Comparable  (0) 2022.11.03
Arrays  (0) 2022.11.03
Stack과 Queue  (0) 2022.11.02
LinkedList  (0) 2022.11.02
ArrayList  (0) 2022.11.01
댓글
공지사항