본문 바로가기
Java의 정석/컬렉션 프레임워크

Iterator, Enumeration / Map 과 Iterator

by Hwanii_ 2023. 9. 20.
728x90

Iterator : 반복하다

 

ch11 - 22 Iterator, ListIterator, Enumeration

 

Iterator : 주로 사용

ListIterator : 양방향 읽기 가능 / 잘 사용 하지 않음

Enumeration : 구버전

 

컬렉션에 저장된 데이터를 접근 할 때 사용하는 인터페이스 이다.

 

[ Iterator 인터페이스의 메서드 ]

 

 

Iterator 인터페이스의 메서드 에서 핵심 메서드는 딱 두가지 이다.

 

1) boolean hasNext()

>> 확인 (true or false 반환)

 

2) Object next()

>> 읽기 ( 데이터 반환 (Object) )

 

두가지 이다.

 

참고로, Enumeration 인터페이스는 구버전 이다.

 

구버전의 코드를 확인하는 일이 있을 수도 있으니, 이정도만 알고 넘어 가면 된다.

 

그냥 Iterator 인터페이스와 Iterator 인터페이스의 메서드를 사용 한다고 생각 하면 된다.

 

[ Enumeration 인터페이스의 메서드 ]

 

 

거의 비슷 하다.

 

ListIterator 는 Iterator의 접근성을 향상시킨 것 이다. (단방향 >> 양방향)

next() 메서드는 다음 요소만 읽을 수 있지만,

 

ListIterator 에서는 previous() 메서드가 있는데, 이전 요소를 읽을 수 있는 메서드 이다.

 

근데 이것을 사용 하려면 ListIterator 을 구현한 클래스 에서만 사용 할 수 있고,

잘 사용 안하기 때문에,

 

Iterator 만 기억 하면 된다.

 

 

 

ch11 - 23 Iterator, ListIterator, Enumeration

 

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

 

컬렉션 == List, Set, Map

 

컬렉션 마다 구조가 다르다.

 

List는 배열의 구조.

 

Set은 집합의 구조.

 

Map은 Key와 Value 한쌍의 구조 이다.

 

그래서 저 요소 (객체) 들을 읽어오는 방식이 모두 다르다.

 

그래서 불편 하다.

(List 컬렉션에는 get(i) 메서드가 있는데, Set 컬렉션에는 get(i) 메서드가 없다던지 ..)

 

이것을 해소 하기 위해 만들어진 것이 Iterator 인터페이스 이다.

 

그냥 hasNext() 메서드로 확인 하고 !

 

next() 메서드로 데이터를 읽어오면 끝이다 !

 

구조가 어떻게 되있는지는 신경 쓰지 않아도 된다.

 

그냥 사용하는쪽 에서는 두가지 메서드만 기억 하고 사용 하면 되니까, 편하다.

 

컬렉션에 iterator() 메서드를 호출 해서 Iterator 를 구현한 객체를 얻어서 사용 하면 된다.

즉, iterator() 메서드의 반환값은 Iterator 타입의 객체 이다.

 

예시)

 

List list = new ArrayList();	//	다른 컬렉션이면 이 부분을 변경.

Iterator it = list.iterator();	//	Iterator 객체 반환.

while(it.hasNext()) {	//	boolean hasNext()

	sysout(it.next());	//	Object next()
    
    //	더이상 읽어올 요소가 없을 때 까지 데이터를 읽어오기
    
}

 

예제 01 )

 

public static void main(String[] args) {
		
    ArrayList list = new ArrayList();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("5");

    Iterator it = list.iterator();	//	Iterator 객체를 얻기.

    System.out.println("log : it.hasNext() : " + it.hasNext());

    while(it.hasNext()) {	//	hasNext() 메서드를 사용 해서 데이터가 있는지 읽기. (포인터의 개념으로 읽는다)

        Object obj = it.next();

        System.out.println(obj);
    }

}

 

log : it.hasNext() : true

1

2

3

4

5

 

위의 코드는 배열리스트에 각 자리에 요소 5개를 추가 하고,

 

컬렉션을 가리키는 참조변수를 주체로 해서 iterator() 메서드를 사용 해서, Iterator 객체를 얻는다.

 

그리고, Iterator 객체는 참조변수 it 이니까, it 를 주체로 해서 hasNext() 메서드를 사용 한다.

 

hasNext() 메서드는 Iterator 객체에 읽어올 데이터가 있는지 체크하는 메서드 인데,

 

포인터 개념으로 읽기 때문에, 한번 쭉 돌면서 Iterator 객체를 다 읽으면,

포인터가 더이상 가리킬 요소 (객체 == 데이터) 가 없기 때문에, false 를 반환 하게 되고,

while 반복문의 조건값이 false 가 되어서 종료 하게 된다.

 

또한 next() 메서드를 사용해서,

모든 타입의 데이터를 obj 변수에 저장 (덮어씌우면서) 하면서,

출력을 하는 코드 이다. 

 

이때 짚고 넘어가야할 개념은, Iterator 타입의 참조변수 it 는 일회용 이다.

 

이게 무슨 말이냐면,

Iterator 은 한번 사용 됬으면,

hasNext() 메서드가 가리킬 객체 == 요소 == 데이터가 없어서,

무조건 false 를 반환 하게 된다.

 

그래서, 무엇을 다시 읽고 데이터를 다시 가져 오고 싶으면, iterator 객체를 다시 얻어야 한다.

 

아래의 로그가 작성된 코드를 확인 하면 이해 하기 쉬울것이다.

 

public static void main(String[] args) {
		
    ArrayList list = new ArrayList();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("5");

    Iterator it = list.iterator();	//	Iterator 객체를 얻기.

    System.out.println("log : it.hasNext() : " + it.hasNext());

    while(it.hasNext()) {	//	hasNext() 메서드를 사용 해서 데이터가 있는지 읽기. (포인터의 개념으로 읽는다)

        Object obj = it.next();

        System.out.println(obj);
    }

    System.out.println("log : it.hasNext() : " + it.hasNext());

    it = list.iterator();

    System.out.println("log : it.hasNext() : " + it.hasNext());

    while(it.hasNext()) {

        Object obj = it.next();

        System.out.println(obj);
    }

    //	참고로 iterator 는 1회용 이다. 한번 사용됬으면 iterator 객체를 다시 얻어 와야 한다.

    //	그래서 위와 같이, 복사를 해서 hasNext() 메서드를 호출 해도,
    //	더이상 읽어올 것 (요소 == 객체) 이 없어서 false 가 나온다.

    //	그래서 다시 얻어 오려면, it = list.iterator() 을 작성 하면 된다.
		
} // main

 

 

한번 while 문을 모두 돌게 되면,

iterator 객체로 hasNext() 메서드를 사용 하면 false 를 반환 하는것을 확인 할 수 있고,

 

it = list.iterator();

 

다시 객체를 얻어 오는 코드를 작성함으로써,

 

iterator 객체로 hasNext() 메서드를 사용한 로그를 찍어보면 true 인것을 확인 할 수 있다.

 

그러기 때문에 while(true) 가 되서, 다시 배열리스트에 있던 데이터를 출력 할 수 있게 됬다.

 

 

 

[ 참고 ]

 

컬렉션 프레임워크를 사용 하다 보면, 성능상에 이유라던지, 기타 등등에 이유로 인해서,

컬렉션 타입을 변경 해야 할 수도 있다.

 

그러니까, ArrayList 를 사용 하다가, 갑자기 HashSet을 사용 할 수 있다는 말인데,

 

처음에 ArrayList list = new ArrayList(); 로 코드를 작성 해서,

 

ArrayList 에 있는 메서드를 막 사용 하고, 그 메서드 중에 get(i) 라는 메서드도 있었다고 해보자.

 

근데, 이후에 Set 인터페이스로 변경 하게 되서,

 

HashSet set = new HashSet() 으로 코드를 변경 했다고 해보자.

 

그러면, HashSet 에는 get(i) 라는 메서드가 없어서 컴파일 에러가 발생 하게 된다.

 

즉, 코드에 유연성이 떨어지게 된다는 의미 이다.

 

그래서, 이 모든 컬렉션 인터페이스의 상위 인터페이스는 Collection 인터페이스 인데,

 

처음에 Collection 인터페이스 자료형으로 참조변수를 선언하게 되면,

 

new 하는 실제 객체는 필요한 객체 클래스를 사용해서 객체화를 하면 유연성을 가지게 된다.

 

가령,

 

Collection c = new TreeSet(); 이라던지,

Collection c = new HashSet(); 이라던지,

Collection c = new LinkedList(); 이라던지,

Collection c = new ArrayList(); 이라던지, 

 

..

 

이런식으로 제일 큰 상위의 인터페이스 자료형으로 참조변수를 설정하게 되면,

 

Collection 인터페이스를 구현한 모든 클래스들을 가리키지만,

 

Collection 인터페이스가 사용 가능한 메서드만 사용 할 수 있게 되기 때문에,

 

이후에, 컬렉션 종류를 변경 하더라도,

(new XxxSet or new XxxList)

 

처음부터 Collection 인터페이스에서 사용 가능한 메서드로만 코드를 작성했을테니까,

 

코드가 굉장히 유연해진다는 장점을 가지게 된다.

 

제네릭 설정을 안해줘서 노란 밑줄 ..

 

 

위의 메서드만 사용 했다는 의미가 된다.

 

 

 

ch11 - 24 Map 과 Iterator

 

Map 에는 iterator() 메서드가 존재 하지 않는다.

 

즉,

List 컬렉션과 Set 컬렉션은 자료를 읽을 수 있는 표준화를 제시한 방법으로 Iterator 을 사용 할 수 있었는데,

Map 컬렉션에는 iterator() 메서드가 없다 !

 

왜 없냐면, Map 인터페이스는 Collection 인터페이스를 상속 받은 인터페이스가 아니기 때문 이다.

 

iterator() 메서드는 Collection 인터페이스 내부에 존재하는 메서드 이다.

 

 

 

그리고, 위와 같이 List 인터페이스는 Collection 인터페이스를 상속 받았는데,

 

 

Map 인터페이스는 아무것도 상속 받지도 않고 뭐가 없다.

따라서, Iterator iterator() 메서드를 사용 할 수 없는 것이다.

 

map 만 없다.

 

 

Map은 keySet(), entrySet(), values() 메서드 등을 사용 해야 한다.

 

위의 메서드를 사용 하면, 다음과 같이 반환값을 얻을 수 있다.

 

keySet() : Set (반환 타입)

 

entrySet() : Set (반환 타입)

 

values() : Collection (반환 타입)

 

 

map 참조변수에 entrySet() 과 같은 메서드를 사용 하고, 거기서 iterator() 메서드를 사용 해야 한다.

 

위의 코드를 두줄로 나누면 다음과 같다.

 

Set entrySet = map.entrySet();

Iterator it = entrySet.iterator();

반응형

'Java의 정석 > 컬렉션 프레임워크' 카테고리의 다른 글

Comparator & Comparable  (0) 2023.09.20
Arrays 클래스  (0) 2023.09.20
Stack / Queue (스택 / 큐)  (0) 2023.09.17
LinkedList 와 ArrayList 의 비교  (0) 2023.09.17
ArrayList와 Java API 확인  (0) 2023.09.17