StringCharacterIterator? 문자열을 반복하는 친구인가?!
1. Iterator과 StringCharacterIterator의 차이
Iterator이란?
An iterator over a collection. Iterator takes the place of Enumeration in the Java Collections Framework.
컬렉션에 대한 반복자입니다. Iterator는 Java Collections Framework에서 Enumeration을 대신합니다.
공식문서에서도 볼 수 있듯이 Iterator은 Collection에 대한 반복자입니다.
Collection은 데이터를 모아서 저장하는 자료구조를 일반화한 개념입니다. 자바에서는 Collection Framework를 제공해 다양한 유형의 컬렉션을 구현하고 사용할 수 있습니다. 자바로 구현할 때 흔히 사용하는 Stack, ArrayList 등 모두 컬렉션을 구현한 클래스입니다.
Collection을 구현한 클래스 보기
Classes:AbstractCollection, AbstractList, AbstractQueue, AbstractSequentialList, AbstractSet, ArrayBlockingQueue, ArrayDeque, ArrayList, AttributeList, BeanContextServicesSupport, BeanContextSupport, ConcurrentHashMap.KeySetView, ConcurrentLinkedDeque, ConcurrentLinkedQueue, ConcurrentSkipListSet, CopyOnWriteArrayList, CopyOnWriteArraySet, DelayQueue, EnumSet, HashSet, JobStateReasons, LinkedBlockingDeque, LinkedBlockingQueue, LinkedHashSet, LinkedList, LinkedTransferQueue, PriorityBlockingQueue, PriorityQueue, RoleList, RoleUnresolvedList, Stack, SynchronousQueue, TreeSet, Vector
StringCharacterIterator이란?
StringCharacterIterator implements the CharacterIterator protocol for a String. The StringCharacterIterator class iterates over the entire String.
StringCharacterIterator은 String에 대한 CharacterIterator 프로토콜을 구현합니다. StringCharacterIterator 클래스는 전체 문자열을 반복합니다.
공식문서를 살펴보면 StringCharacterIterator은 Iterator처럼 반복을 하지만 문자열(String)을 반복한다고 했습니다.
Iterator과 StringCharacterIterator의 차이점은 바로 반복하는 대상입니다.
Iterator은 Collection을 반복하고 StringCharacterIterator은 문자열을 반복합니다.
2. StringCharacterIterator 메서드 분해하기
1. 생성자
StringCharacterIterator은 3가지의 생성자를 제공합니다.
1. text (문자열만 받는 생성자)
StringCharacterIterator(String text)
생성자가 매개변수로 문자열만 받는다면 초기 인덱스가 0인 반복기(Iterator)을 생성합니다.
2. text, pos (문자열, 초기 인덱스를 받는 생성자)
StringCharacterIterator(String text, int pos)
생성자가 매개변수로 문자열과 초기 인덱스를 받는다면 초기 인덱스부터 반복하는 반복기(Iterator)을 생성합니다.
3. text, begin, end, pos (문자열, 지정된 범위, 초기 인덱스를 받는 생성자)
StringCharacterIterator(String text, int begin, int end, int pos)
생성자가 문자열, 지정된 범위, 초기 인덱스를 받으면 지정된 범위 내에서 초기 인덱스부터 반복하는 반복기(Iterator)을 생성합니다.
2. setText
public void setText(String text) {
if (text == null)
throw new NullPointerException();
this.text = text;
this.begin = 0;
this.end = text.length();
this.pos = 0;
}
text가 비어있는 경우 NullPointerException을 발생시키며, 반복기(Iterator)을 이 문자열에 대해 초기화시킵니다.
반복기(Iterator)에 새로운 문자열을 적용시키고 싶을 때 사용하는 메서드입니다.
3. current
public char current()
{
if (pos >= begin && pos < end) {
return text.charAt(pos);
}
else {
return DONE;
}
}
현재 위치한 인덱스가 지정된 범위 안에 있으면 인덱스에 위치한 문자를 반환하고, 만약 지정된 범위를 벗어났으면 DONE을 반환합니다.
4. first
public char first()
{
pos = begin;
return current();
}
지정된 범위 중, 인덱스를 시작점(begin)으로 설정하고 current함수를 호출합니다.
current함수는 인덱스에 해당하는 문자를 반환하므로 first함수는 시작점에 위치한 문자가 반환됩니다.
5. last
public char last()
{
if (end != begin) {
pos = end - 1;
} else {
pos = end;
}
return current();
}
지정된 범위 중, 인덱스를 끝(end)으로 설정하고 current 함수를 호출합니다.
if 조건문으로 end와 begin을 비교하고 같지 않으면 -1을 해주는 이유는 문자열의 인덱스는 0부터 시작하는데 길이는 1부터 시작해 -1을 해주는 것입니다.
6. setIndex
public char setIndex(int p)
{
if (p < begin || p > end)
throw new IllegalArgumentException("Invalid index");
pos = p;
return current();
}
매개변수(p)가 지정된 범위 안에 있으면 인덱스값을 p로 설정한 뒤, current 함수 호출한다.
만약 시작값보다 작거나, 끝값보다 크면 IllegalArgumentException을 발생시킨다.
7. next
public char next()
{
if (pos < end - 1) {
pos++;
return text.charAt(pos);
}
else {
pos = end;
return DONE;
}
}
현재 인덱스 값(pos)이 끝(end)과 비교했을 때 작다면, 현재 인덱스 값(pos)에서 1을 더한 위치에 있는 문자를 반환합니다.
pos < end - 1을 한 이유는 end에서 -1을 해야 마지막 위치의 인덱스를 얻을 수 있기 때문입니다. // last 함수 추가설명 보시면 됩니다.
8. previous
public char previous()
{
if (pos > begin) {
pos--;
return text.charAt(pos);
}
else {
return DONE;
}
}
현재 인덱스가 시작값보다 크다면 현재 인덱스 값에서 1을 뺀 위치에 있는 문자를 반환합니다.
3. 관련 문제
https://algospot.com/judge/problem/read/QUADTREE
정답 코드(문제에 대한 풀이는 다른 게시물에 올리겠습니다)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.StringCharacterIterator;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
public class QuadTree {
static String pic;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int c = Integer.parseInt(st.nextToken());
while (c-- > 0) {
st = new StringTokenizer(br.readLine());
pic = st.nextToken();
StringCharacterIterator iterator = new StringCharacterIterator(pic);
System.out.println(reverse(iterator));
}
}
static String reverse(StringCharacterIterator picture) {
char head = picture.current();
picture.next();
/*
head의 값이 w or b이면 char 값을 반환한다.
이 조건문을 통해 만약 head의 값이 x이면 return을 하지 않고 재귀 함수를 호출하게 한다.
*/
if (head == 'w' || head == 'b') {
return String.valueOf(head);
}
String topLeft = reverse(picture);
String topRight = reverse(picture);
String bottomLeft = reverse(picture);
String bottomRignt = reverse(picture);
return "x" + bottomLeft + bottomRignt + topLeft + topRight;
}
}
4. 참고 문헌