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가 가장 어울린다고 생각합니다.

Posted by
,