public Board[] findAll() {
Board[] arr = list.toArray(new Board[0]);
// 역순으로 정렬하여 리턴한다.
Board[] arr2 = new Board[arr.length];
for(int i=0;i<arr2.length;i++) {
arr2[i] = arr[arr.length-i-1];
}
return arr2;
}
⇒ 데이터 목록 객체의 종류(ArrayList, LinkedList, Stack, Queue)에 상관 없이 일관된 방법으로 꺼내기 위해 Iterator를 사용하자!
→ 각각의 데이터 자료주고에서 제공하는 메서드를 사용하여 데이터를 직접 꺼내지 말고 값을 꺼내주는 객체의 도움을 받자!
class A{ //← class A 안에 있는 class들은 모두 Nested class(중첩 클래스)들이다.
static class X{} //← static nested class (after2)
class Y {} //← non-static nested class = inner class (after3)
void m1(){
class Z{} //← local class
}
}
class B{} //← package member class (after1)
1. 패키지 멤버로 Iterator 클래스 정의하기
2. 클래스 멤버(스태틱 중첩 클래스)로 Iterator 클래스 정의하기
3. 인스턴스 멤버(논 스태틱 주첩 클래스 = inner class)로 Iterator 클래스 정의하기
4. 로컬 클래스로 Iterator 클래스 정의하기
5. 익명 클래스로 Iterator 클래스 정의하기
// 데이터 조회를 수행하는 객체 사용법 정의
public interface Iterator<E> {
// 목록에 조회할 데이터가 있는지 검사할 때 호출
boolean hasNext();
// 목록에서 데이터를 한 개 꺼낼 때 호출
E next();
}
public class Test01 {
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>();
list1.add("aaa");
list1.add("bbb");
list1.add("ccc");
list1.add("ddd");
Iterator<String> iterator = list1.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + ",");
}
System.out.println();
}
}
// ArrayList에서 데이터를 꺼내줄 객체
//
public class ArrayListIterator<E> implements Iterator<E> {
ArrayList<E> list;
int index = 0;
public ArrayListIterator(ArrayList<E> list) {
this.list = list;
}
@Override
public boolean hasNext() {
return index < list.size();
}
@Override
public E next() {
return list.get(index++);
}
}
public class ArrayList<E> {
static final int DEFAULT_SIZE = 5;
Object[] arr;
int size;
public ArrayList() {
this(0); //여기서 0은 밑의 생성자에 0을 넘겨줘서 사용할 새로운 배열을 생성하게 한다.
}
public ArrayList(int capacity) {
if (capacity > DEFAULT_SIZE)
arr = new Object[capacity];
else
arr = new Object[DEFAULT_SIZE];
}
public Object[] toArray() {
Object[] list = new Object[this.size];
for (int i = 0; i < this.size; i++) {
list[i] = this.arr[i];
}
return list;
}
public void add(E value) {
if (this.size == arr.length)
increase();
arr[this.size++] = value;
}
public int insert(int index, E value) {
if (index < 0 || index >= size)
return -1;
if (this.size == arr.length)
increase();
for (int i = size - 1; i >= index; i--)
this.arr[i + 1] = this.arr[i];
this.arr[index] = value;
size++;
return 0;
}
@SuppressWarnings("unchecked")
public E get(int index) {
if (index < 0 || index >= size)
return null;
return (E) this.arr[index];
}
@SuppressWarnings("unchecked")
public E set(int index, E value) {
if (index < 0 || index >= size)
return null;
E old = (E) this.arr[index];
this.arr[index] = value;
return old;
}
@SuppressWarnings("unchecked")
public E remove(int index) {
if (index < 0 || index >= size)
return null;
E old = (E) this.arr[index];
for (int i = index; i < size - 1; i++)
this.arr[i] = this.arr[i+1];
size--;
return old;
}
public int size() {
return this.size;
}
private void increase() {
int originSize = arr.length;
int newSize = originSize + (originSize >> 1);
Object[] temp = new Object[newSize];
for (int i = 0; i < this.arr.length; i++) {
temp[i] = this.arr[i];
}
arr = temp;
}
// Iterator 구현체를 제공한다.
public Iterator<E> iterator() {
return new ArrayListIterator<E>(this);
}
}
public class ArrayList<E> {
...(동일 코드 생략)
// Iterator 구현체를 제공한다.
public Iterator<E> iterator(){
return new ArrayListIterator<E>(this); // list 변수 주소 값이 this에 넘어간다.
}
// static nested class(스태틱 중첩 클래스)
static class ArrayListIterator<E> implements Iterator<E> {
ArrayList<E> list;
int index=0;
public ArrayListIterator(ArrayList<E> list) {
this.list = list;
}
@Override
public boolean hasNext() {
return index < list.size();
}
@Override
public E next() {
return list.get(index++);
}
}
}
바깥클래스명.this.멤버
와 같이 접근이 가능하다!public class ArrayList<E> {
...(동일 코드 생략)
// Iterator 구현체를 제공한다.
public Iterator<E> iterator() {
// 생성자를 호출할 때 바깥 클래스의 인스턴스 주소를 넘겨주지 않아도
// 컴파일러가 넘겨주는 코드로 자동 변환한다.
//
return new ArrayListIterator<E>();
// 위의 코드는 컴파일 될 때 다음과 같이 바뀐다.
// return new ArrayListIterator<E>(this);
}
// non-static nested class(스태틱 중첩 클래스) = inner class
class ArrayListIterator<T> implements Iterator<T> {
// 논스태틱 중첩 클래스인 경우 바깥 클래스의 인스턴스 주소를 받을 필드가 자동 추가된다.
// 따라서 다음과 같이 개발가 직접 추가할 필요가 없다.
// ArrayList<E> this$0; // 자동 생성 된다.
int index = 0;
// 논스태틱 중첩 클래스인 경우 바깥 클래스의 인스턴스 주소를 받는 파라미터가
// 생성자가 자동으로 추가된다.
// 개발자가 직접 추가할 필요가 없다.
// public ArrayListIterator(ArrayList<E> this$0) {
// this.this$0 = this$0;
// }
@Override
public boolean hasNext() {
// 컴파일러가 자동으로 추가한,
// 바깥 클래스의 인스턴스 주소를 담고 있는 변수를 사용하려면 다음과 같이 지정하라!
// 바깥클래스명.this.멤버
//
return index < ArrayList.this.size();
}
@SuppressWarnings("unchecked")
@Override
public T next() {
// 컴파일러가 추가한 바깥 클래스의 인스턴스 주소를 사용하고 싶다면
// ArrayList.this 라고 지정하면 된다.
// ArrayList.get() 메서드의 리턴 타입이 E 이다.
// E가 가리키는 타입 정보는 다음과 같이 결국 ArrayListIterator를 만들 때 넘겨진다.
// new ArrayListIterator<E>();
// 따라서 ArrayListIterator 내부에서 사용하는 T가 곧 ArrayList 의 E와 같다.
// 결론! 다음과 같이 형변환 할 수 있다.
return (T) ArrayList.this.get(index++);
}
}
}
public class ArrayList<E> {
...(동일 코드 생략)
// Iterator 구현체를 제공한다.
public Iterator<E> iterator() {
// local class(로컬 클래스)
class ArrayListIterator<T> implements Iterator<T> {
int index = 0;
@Override
public boolean hasNext() {
return index < ArrayList.this.size();
}
@SuppressWarnings("unchecked")
@Override
public T next() {
return (T) ArrayList.this.get(index++);
}
}
return new ArrayListIterator<E>();
}
}
인터페이스명 레퍼런스 = new 인터페이스명() {
인터페이스에 선언된 메서드 구현
};
public class ArrayList<E> {
...(동일 코드 생략)
// Iterator 구현체를 제공한다.
public Iterator<E> iterator() {
// anonymous class(익명 클래스)
Iterator<E> iterator = new Iterator<>() {
int index = 0;
@Override
public boolean hasNext() {
return index < ArrayList.this.size();
}
@Override
public E next() {
return ArrayList.this.get(index++);
}
};
return iterator;
}
}
변수 생성 없이 바로 리턴할 수도 있다.
public class ArrayList<E> {
...(동일 코드 생략)
// Iterator 구현체를 제공한다.
public Iterator<E> iterator() {
// anonymous class(익명 클래스)
return new Iterator<>() {
int index = 0;
@Override
public boolean hasNext() {
return index < ArrayList.this.size();
}
@Override
public E next() {
return ArrayList.this.get(index++);
}
};
}
}