자바(Java) 강의

자바 Collection Iterator

삐멜 2019. 5. 4. 16:11

이번 포스트에서는 자바의 Collection을 반복하는 몇가지 방법에 대해 소개하도록 한다. 특히 반복문이 아닌 Collection이 구현하는 Iterator 인터페이스를 이용해 반복하는 방법을 다룬다. 또한 이 포스트에서는 List/Set과 같이 단독 엘리멘트를 저장하는 컬렉션과 Map처럼 Key-Value 페어를 저장하는 컬렉션의 예제를 포함한다.

목표

  • Iterator

  • while을 이용하는 방법

  • for를 이용하는 방법

  • ***for-each를 이용하는 방법 

  • ***stream for-each를 이용하는 방법 

***은 많이 쓰이는 방법을 의미한다. 다 읽을 시간이 없고 당장 써먹고 싶으면 ***만 읽어도 좋다.

Iterator

Iterator 인터페이스로 반복을 하기 위해서는 몇 가지 메서드를 알아야 한다. 첫번째는 iterator메서드, 두번째는 hasNext와 next메서드이다.

iterator() 메서드는 Iterator를 사용하는 모든 Collection이 구현하는 메서드이다. 이 메서드는 Iterator 인터페이스를 리턴한다.

hasNext() 메서드는 말 그대로, 이 다음번 엘리먼트가 존재하면 true, 존재하지 않으면 false를 리턴한다. 따라서 hasNext를 이용해 언제 반복을 중단해야하는지 알 수 있다. next() 메서드는 해당 반복의 다음 엘리먼트를 리턴한다. 예를 들어 List에 1, 2, 3이 들어있다고 치자. next()를 하면 1을 리턴한다. 그 다음 바로 next()를 또 하면 2를 리턴한다. 

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Main {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);

Iterator<Integer> it = list.iterator();
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());

}
} 1 2 3

it.next를 할 때마다 한 칸씩 다음 엘리먼트로 넘어간다고 생각하면 쉽다. 이제 각종 반복문을 이용해 반복하는 방법에 대해 알아보자.

while을 이용하는 방법

List를 이용한 예제

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Main {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);

Iterator<Integer> it = list.iterator();
while(it.hasNext()) {
Integer element = it.next();
System.out.println(element);
}

}
}

위처럼 List 컬렉션에 존재하는 iterator를 불러와 사용할 수 있다.

Map을 이용한 예제

import java.util.*;

public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");

Iterator<Integer> it = map.keySet().iterator();
while(it.hasNext()) {
Integer key = it.next();
String value = map.get(key);
System.out.println(key + " - " + value);
}
} }

Map은 key, value로 다뤄야 하기 때문에 keySet의 iterator를 가져와 이를 반복한다. Entry를 이용하는 방법도 있다.

import java.util.*;

public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");

Iterator<Map.Entry<Integer,String>> it = map.entrySet().iterator();
while(it.hasNext()) {
Map.Entry<Integer, String> entry = it.next();
System.out.println(entry.getKey() + " - " + entry.getValue());
}
}
}

for를 이용하는 방법

List를 이용한 예제

import java.util.*;

public class Main {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);

for(Iterator<Integer> it = list.iterator(); it.hasNext();) {
System.out.println(it.next());
}
} }

반복문에 while에서 했던 것과 마찬가지로 조건을 넣어 반복해준다.

Map을 이용한 예제

import java.util.*;

public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");

for (Iterator<Integer> it = map.keySet().iterator(); it.hasNext(); ) {
Integer key = it.next();
String value = map.get(key);
System.out.println(key + " - " + value);
}
} }

Entry를 이용하는 방법은 아래와 같다.

import java.util.*;

public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");

for (Iterator<Map.Entry<Integer,String>> it = map.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<Integer, String> entry = it.next();
System.out.println(entry.getKey() + " - " + entry.getValue());
}
}
}

***for-each를 이용하는 방법 

for-each는 간단해 아주 많이 쓰인다.

List를 이용하는 방법

import java.util.*;

public class Main {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);

for(Integer element : list) {
System.out.println(element);
}
} }

element에는 1->2->3이 차례대로 들어갈 것이다. 말그대로 list에 있는 엘리먼트를 하나씩 element라는 변수에 넣고 아래의 코드를 실행하라는 뜻이다. 

Collection이 구현하는 foreach를 이용 할 수도 있다. (Java 8)

import java.util.*;

public class Main {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);

list.forEach(System.out::println);
}
}

Map을 이용한 예제

import java.util.*;

public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");

for (Integer key : map.keySet() ) {
System.out.println(key + " - " + map.get(key));
}
}
}

entrySet을 이용하는 방법은 아래와 같다.

import java.util.*;

public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");

for (Map.Entry<Integer,String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " - " + entry.getValue());
}
}
}

마찬가지로 Collection이 구현하는 forEach를 이용하는 방법도 있다. 내 생각엔 가장 간결한 방법인것 같다.

import java.util.*;

public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");

map.forEach((key, value) -> System.out.println(key + " - " + value));
}
}

***stream for-each를 이용하는 방법 

java 8이후로는 stream을 이용하는 방법도 많이 사용되고 있다. Stream foreach의 경우는 단독으로 사용하는 경우는 별로 없다. 위에서 Collection이 구현하는 forEach를 사용하면 되기 때문이다. 하지만 stream이 제공하는 filter/map같은 다른 메서드를 사용후 forEach를 해야하는 경우 유용하다.

List를 이용한 예제

import java.util.*;

public class Main {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);

list.stream().forEach(System.out::println);         // 또는 list.stream().forEach(e -> System.out.println(e));
}
}

Map을 이용한 예제

import java.util.*;

public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");

map.keySet().stream().forEach(key -> System.out.println( key + " - " + map.get(key)));
}
}

Entry를 이용하는 방법은 다음과 같다.

import java.util.*;

public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");

map.entrySet().stream()             .forEach(entry -> System.out.println(entry.getKey() + " - " + entry.getValue()));
}
}

이번 포스트에서는 자바의 Iterator를 이용해 Collection을 반복하는 방법에 대해 알아보았다. 새로 배운게 있거나 유용한 정보라고 생각하면 하트를 눌르자.