자바를 이용해서 컬렉션 데이터를 처리할 때 반복문을 많이 사용한다. for 문을 이용해서 컬렉션 데이터 하나하나를 처리하는 코드는 일반적으로 다음과 같을 것이다.
public static void main(String[] args) {
int array[] = {1, 2, 3, 4, 5};
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
// 출력
// 1
// 2
// 3
// 4
// 5
초기부터 자바를 사용해 왔거나 C 언어 같은 언어를 사용하던 프로그래머라면 이런 형태의 코드가 자연스럽게 받아들여질 것이다. 하지만 JDK 5.0 버전부터 for each 구문을 제공하면서 더 간결하게 컬렉션 데이터를 사용할 수 있게 되었다.
public static void main(String[] args) {
int array[] = {1, 2, 3, 4, 5};
for (int number : array) {
System.out.println(array[i]);
}
}
// 출력
// 1
// 2
// 3
// 4
// 5
이미 모던 프로그래밍 언어에서는 지원하고 있던 형태의 문법이다. for 문을 사용하여 컬렉션의 인덱스를 사용해야 했던 부분이 깔끔하게 컬렉션 데이터를 하나씩 뽑아주는 형태로 변경되었다. 이렇게 되면 배열의 경우 IndexOutOfBoundsException 같은 위협이 사라지게 된다.
for each 구문을 사용할 때 주의해야 할 점은 for each 구문으로 컬렉션 데이터를 처리할 때, 컬렉션은 수정할 수 없다는 점이다.
이미 모던 프로그래밍 언어에서는 지원하고 있던 문법이다. for 문이 보다 깔끔해지고, array의 IndexOutOfBoundsException 같은 위협이 없어졌다. 이 향상된 for 문을 이용하면 컬렉션에서 항목을 뽑아내는 작업이 int number : array 한줄로 안전하게 이뤄진다.
for each 구문에 사용할 수 있는 클래스
for each 구문을 사용할 때 컬렉션 데이터만 사용할 수 있는건 아니다. 사용자가 정의한 클래스도 컬렉션처럼 for each 구문에 사용할 수 있다. 다만 for each 구문에 사용하려면 'java.lang'Iterable' 인터페이스를 구현해야한다. DB나 파일 서버에서 Record 하나씩 꺼내와서 for 문을 돌리는데 클래스를 구현해서 사용하면 깔끔해지고 좋다.
사용자가 정의한 클래스를 for each 구문에 사용한 예를 살펴보자.
public class Test {
public static void main(String []args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
TestIterable<Integer> testIterable = new TestIterable<Integer>(list);
for (int item : testIterable) {
System.out.println(item);
}
}
}
for each 구문에 사용한 testIterable 객체는 분명 컬렉션 타입은 아니다. TestIterable 클래스의 정의를 살펴보자.
public class TestIterable<Integer> implements Iterable<Integer> {
class TestIterator<Integer> implements Iterator<Integer> {
private final List<Integer> list;
public TestIterator(List<Integer> list) {
this.list = list;
}
public boolean hasNext() {
return list.size() > 0;
}
public Integer next() {
return list.get(0);
}
public void remove() {
list.remove(0);
}
}
private final Iterator<Integer> iterator;
public TestIterable(List<Integer> list) {
iterator = new TestIterator<Integer>(list);
}
public Iterator<Integer> iterator() {
return iterator;
}
}
Integer 데이터를 반환해주도록 지내릭 타입을 주고 Iterable 인터페이스를 구현했다. Iterable 인터페이스는 Iterator 객체를 리턴하게 되는데, Iterator 인터페이스를 구현한 클래스도 정의해 줬다.
for each 구문을 사용하면 코드가 깔끔해지고 가독성도 높아지는 장점을 얻을 수 있다.
댓글