List 인터페이스
컬렉션 가운데 List가 갖는 가장 큰 특징은 List가 갖고 있는 객체의 순서가 있다는
것입니다. 순서가 있다는 것은 List가 갖고 있는 객체마다 순서 번호(인덱스)를 갖고
있다는 뜻입니다. List는 배열과 같이 리스트가 갖고 있는 몇 번째 객체를 직접 참조할 수
있습니다.
리스트는 객체의 순서를 항상 관리하고 있기 때문에 리스트에 객체를 추가할 때 리스트의
맨 끝 부분에만 추가하는 것이 아니라 원하는 위치에 객체를 추가할 수도 있습니다.
List는 Collection 인터페이스에 비해서 상당히 기능이 많아졌습니다.
가장 기본적인 특징은 위치를 지정하여 객체를 꺼낼 수 있고, List의 부분집합을 List로
구할 수 있습니다. 그리고 Collection이 가지는 Iterator인터페이스 뿐만 아니라 ListIterator
라는 인터페이스를 이용할 수 있습니다.
List가 Set과 대별되는 가장 큰 특징은 List는 중복되는 객체를 가질 수 있습니다.
인덱스를 이용해서 객체를 한번에 꺼낼수 도, 삭제할 수도 있습니다. Collectin 및 Set의
경우는 객체를 꺼내려고 할 때는 Iterator 인터페이스를 이용해서 객체를 꺼낼 수 밖에
없지만 List의 경우는 옵션이 하나더 생긴셈입니다.
필자의 경우 컬렉션 프레임워크에서 List를 가장 많이 사용하는데 이는 List가 가진 이
특징 때문입니다.
List | |
Object get(int index) |
List의 index번째 객체를 꺼냅니다. List의 index번째 객체 |
int indexOf(Object o) |
List에 객체 o가 나타나는 첫번째 인덱스 List에 객체 o가 없다면 - 1 |
int lastIndexOf(Object o) |
List에 객체 o가 나타나는 마지막 인덱스 List에 객체 o가 없다면 - 1 |
ListIterator listIterator() |
List의 ListIterator |
ListIterator listIterator(int index) |
List의 index부터 시작한 ListIterator |
Object set(int index, Object o) |
List의 index번째에 객체를 객체 o로 바꿉니다. index번째에 있었던 이전 객체 |
List subList(int from,int to) |
List의 from번째부터 to번째까지 객체를 List로 리턴 |
표 5 - 3
ListIterator 인터페이스
ListIterator는 Iterator를 상속한 인터페이스입니다.
Collection에서 제공하는 Iterator인터페이스는 Collection을 한방향으로 탐색하면서 객체에 대한 정보를 얻어냅니다.
ListIterator는 List에서 제공하는 인터페이스로 List에 포함된 모든 객체를 양방향으로
탐색하면서 객체를 꺼낼 수 있는 방법을 제공하고 있습니다.
프로그래머는 ListIterator 이용하면 양방향으로 움직여가면서 수정이라던가,iterator의
현재 위치를 알아낼수 있습니다. List를 사용하는 경우에는 Collection에서 제공하는 Iterator
는 물론이거니와 보다 확장된 기능을 갖고 있는 ListIterator를 사용할 수 있습니다.
ListIterator | |
boolean hasNext() |
Iterator를 앞방향으로 진행하며 객체를 확인합니다. iteration이 객체(elements)를 더 갖고 있으면 true 그외 false |
boolean hasPrevious() |
Iterator가 반대방향으로 진행하며 객체를 확인합니다. iteration이 객체(elements)를 더 갖고 있으면 true 그외 false |
Object next() |
iteration에서 다음 객체를 리턴 |
Object previous() |
iteration에서 이전 객체를 리턴 |
void remove() |
next() 또는 previous()로 리턴된 마지막 객체를 제거 |
void set(Object o) |
next() 또는 previous()로 리턴된 마지막 객체와 o를 바꿉니다. |
int nextIndex() |
next() 호출로 리턴될 객체의 인덱스 |
int previousIndex() |
previous()호출로 리턴될 객체의 인덱스 |
void add(Object o) |
list에 객체 o를 추가합니다. |
표 5 - 4
import java.util.*;
/**
* List 의 기본 사용법을 보여줍니다.
*/
public class ListDemo {
public void print(List list) {
// 짝수만 추가 0 부터 9까지 2 씩 증가합니다.
for(int i = 0; i < 10; i += 2)
list.add(new Integer(i));
// 인덱스를 이용하여 객체를 직접 참조
for(int i = 0 ; i < list.size(); i++)
System.out.print(list.get(i) + " ");
System.out.println();
// 홀수를 짝수 사이에 추가함 1 부터 10까지 2 씩 증가합니다.
for(int i = 1; i < 10; i +=2)
list.add(i,new Integer(i));
// 인덱스를 이용하여 객체를 직접 참조
for(int i = 0 ; i < list.size(); i++)
System.out.print(list.get(i) + " ");
System.out.println();
// 특정한 인덱스부터 Iteration을 할 수 있습니다.
for(ListIterator it = list.listIterator(list.size()); it.hasPrevious(); ) {
System.out.print(it.previous() + " ");
}
System.out.println();
}
public static void main(String[] args) {
ListDemo demo = new ListDemo();
demo.print(new Vector()); // Vector는 대표적인 List입니다.
}
}
예제 5 - 4 ListDemo.java
그림 5 - 4 [ run ListDemo]
ListDemo 클래스는 List의 주요 기능을 간명하게 나타낸 것입니다.
List는 Collection과 달리 순서가 있기 때문에 순서를 의미하는 인덱스를 통해서 객체를
참조할 수 있습니다. List가 갖고 있는 객체를 모두 한번씩 참조하는 방법으로는
Collection에서 제공하는 Iterator를 이용할 수 있고, List에서 제공하는 ListIterator를 이용
할 수도 있고,직접 인덱스를 이용하여 바로 참조할 수도 있습니다.
예제 5 - 4에서는 List가 갖고 있는 객체를 참조 하기위해 Iterator를 사용하지 않고
0번째 인덱스에서 마지막 인덱스를 반복문 안에서 사용하고 있습니다.
Iterator를 이용하지 않고도 원하는 위치에 있는 객체를 바로 참조할 수 있는 것이
Collection이나, Set에 비해서 List를 많이 사용하게 하는 이유 중 하나입니다.
그리고 List는 순서의 의미를 갖고 있기 때문에 객체를 List의 끝부분에만 추가할 수 있는
것이 아니라 지정한 위치에 객체를 추가할 수 있습니다.
List를 사용함으로써 Collection을 사용할때보다 유연성은 좀 떨어졌지만( 폴리모피즘을
사용할 때 Collection 이지만 List가 아닌경우는 사용할 수 없겠지만) 인덱스를 이용해서
객체를 직접 참조할 수 있기 때문에 객체를 꺼내서 사용하기 위해서 Iterator 인터페이스를
반드시 이용 해야만 하는 Collection 보다는 많이 편하게 사용할 수 있습니다.
예제 5 - 4의 ListDemo클래스의 public void print(List list) 에서는 0,2,4,6,8의 짝수 값을
가지는 Integer 객체를 순서대로 저장한 다음 , 1, 3, 5, 7, 9 홀수의 값을 가지는 Integer
객체를 List의 1,3,5,7,9번째위치에 추가하고 있습니다. 일반 Collection은 객체를 추가할 때
Collection의 가장 뒷 부분에 추가 되지만 List의 경우는 객체가 순서를 유지하고 있기
때문에 List의 지정한 위치에 객체를 추가할 수 있습니다. 물론 이것은 컬렉션중에 List이기
때문에 가능한 것입니다.
그리고 List는 Collection의 Iterator보다 확장된 ListIterator를 사용할 수 있습니다.
ListIterator가 Iterator보다 확장된 기능은 양방향으로 탐색이 가능하다는 것입니다.
예제 5 - 4에서는 ListIterator가 List의 맨 뒤쪽에서 부터 Iteration을 해보았습니다.
List는 Collection이기도 하지만 Collection보다는 훨씬 풍부한 기능을 갖고 있습니다.
예제 5 - 4의 ListDemo에서는 public void static main(String[]) Vector클래스를
사용하고 있는데 Vector 야 말로 ArrayList와 더불어 대표적인 List 입니다.
ListDemo에서도 폴리모피즘을 사용하고 있습니다.
폴리모피즘을 이용한 설계가 상당히 유연스럽다는 것을 고려해본다면 메소드의 인자나,
객체의 레퍼런스에 인터페이스형을 사용하는 것이 상당히 바람직하다고 생각합니다.
하지만 많은 분들이 Vector 나 ArrayList 를 사용할 때
Vector v = new Vector();
ArrayList l = new ArrayList();
예제 5 - 5
등으로 사용하는 것을 보았습니다.
예제 5 - 5의 사용방법은 필자의 생각은 바람직 하다고 생각하지 않습니다.
바람직하지 않다고 생각하는 이유를 예를들어 설명해보겠습니다.
예제 5 - 4의 ListDemo 클래스 설계자가 ListDemo의 메소드를 public void print(List list)
로 하지 않고, public void print(Vector v)로 했다면 어땠을까요?
public static void main(String[] args) {
ListDemo demo = new ListDemo();
demo.print(new ArrayList()); // ! Oops
}
예제 5 - 6
예제 5 - 6 처럼 ArrayList객체는 사용할 수 없습니다. Vector클래스는 자바의 초기때
부터 만들어진 것이고, ArrayList 클래스는 그 다음에 나왔는데, 속도면에서 ArrayList가
좀더 빠르기 때문에 Vector를 굳이 사용해야할 필요가 없고, 대부분 ArrayList를 사용하지만
ListDemo클래스의 메소드 public void print(Vector v)의 경우는 메소드 인자가 Vector클래스
만 있으므로 ArrayList를 사용할 수 없습니다.
그리고 만약 프로그래머 혼자 사는 세상이라면 이것은 비교적 문제가 되지 않습니다.
왜냐하면 ListDemo를 만든 설계자와 ListDemo를 사용하는 사람이 항상 같으니까요.
ListDemo를 설계한 프로그래머는 ListDemo의 public void print(Vector v)메소드를 사용할때
메소드 인자로 항상 Vector객체를 사용할 것입니다.
하지만 ListDemo 클래스를 만든 설계자와 ListDemo를 사용하는 사람이 다를 경우는
ListDemo 클래스 설계자가 public void print(Vector v) 메소드의 인자형을 Vector클래스형
으로 만든 것은 의미가 달라집니다. 이와 같은 경우 ListDemo 클래스 설계자는 ListDemo
의 public void print(Vector v)를 이용하고자 한다면 메소드의 인자로는 반드시 Vector 객체를 사용해야 한다라고 강제한 것이 됩니다. 즉, 실제로는 같은 기능을 하는 ArrayList를
사용해서는 안된다는 뜻입니다. 오직 Vector객체만 사용하라는 뜻입니다.
만약 어떤 프로그래머가 ArrayList 객체에 홀수와 짝수 Integer형 객체를 더하고 싶어서
ListDemo의 public void print(Vector v)를 사용하고자 한다면 그 프로그래머는 어떻게
해야 하겠습니까? 그 프로그래머는 눈물을 머금고 ListDemo2를 스스로 만들던가 아니면
설계자에게 public void print(ArrayList list)를 메소드 오버로딩해 달라고 요청합니다.
물론 이것 보다 더 바람직한 것은 ListDemo클래스의 설계자가 public void print(Vector v)
메소드의 인자를 Vector로 하지 않고 List로 해주는 것이 더 좋습니다.
폴리모피즘을 이용한 설계를 하는 것이 좋다는 뜻입니다.
실제로 ListDemo클래스의 public void print(List list)의 메소드를 살펴보면 List 인터페이스
에서 선언한 메소드만을 가지고 public void print(List list)의 내용을 충분히 구현하고
있습니다. 이런 것을 염두해 둔다면 ListDemo클래스 설계자는 자신이 구현하고자 목표를
구현할 수 있는 범위 안에서(인터페이스가 제공하는 메소드로 구현이 가능하다면 그
인터페이스 범위 안에서) 공통의 개념을 사용하는 것이 좋겠습니다.
여기서는 List가 가장 어울린다고 생각합니다.
'자바 Basic > 자바컬렉션' 카테고리의 다른 글
자바공부-7.Comparable 인터페이스 (0) | 2007.12.06 |
---|---|
자바공부-6.Sorted Set 인터페이스 (0) | 2007.12.06 |
자바공부-4.Set 인터페이스 (1) | 2007.12.06 |
자바공부-3.이터레이터(Iterator) 인터페이스 (0) | 2007.12.05 |
자바공부-2.컬렉션(Collection) 인터페이스 (1) | 2007.12.05 |