반응형

 

 

 - Enumeration, Iterator, ListIterator는 모두 컬렉션에 저장된 요소를 접근하는데 사용되는 인터페이스입니다.

   Enumeration은 Iterator의 구버전이며, ListIterator는 Iterator의 기능을 향상 시킨 것입니다. 자, 이제 하나씩 자세히 살펴보겠습니다.

 

1. Iterator 인터페이스

 

 - Vector 컬렉션 클래스, ArrayList 컬렉션 클래스, LinkedList 컬렉션 클래스와 같이 요소가 순서대로 저장된 컬렉션에서 요소를 순차적으로 검색할 때는

   java.util 패키지에 속한 Iterator 인터페이스를 사용하면 편리합니다.

 

 - List인터페이스 뿐만 아니라, Set인터페이스를 구현한 컬렉션에도 사용 가능합니다. 다음은 Iterator인터페이스의 주요 메서드입니다.

 

 

<사진 1.1> Iterator인터페이스 메서드

 

 - hasNext()메서드와 next()메서드는 Iterator의 핵심 메서드입니다.

 - remove()메서드의 설명에 '선택적 기능'이란 Iterator인터페이스를 구현할 때 remove()메서드가 필수 기능이 아니므로 구현하지

   않아도 괜찮다는 뜻 입니다. 

 - 다음은 ArrayList에 저장된 모든 요소들을 출력하기 위한 코드입니다.

 

1
2
3
4
5
6
List lit = new ArrayList();
 
Iterator it = list.iterator();
while(it.hasNext()) {
    System.out.println(it.next());
}
cs

<사진 1.2>

 

- ArrayList컬렉션 클래스 대신에 List인터페이스를 구현한 다른 컬렉션 클래스(Vector, LinkedList 등)에 대해서도 이와 동일한 코드를

  사용할 수 있습니다. 첫 줄에서 ArrayList대신에 List인터페이스를 구현한 다른 컬렉션 클래스의 객체를 생성하도록 변경하기만 하면 됩니다.

** Map인터페이스는 Collection인터페이스의 자손이 아니므로 iterator()메서드가 존재하지 않습니다.

   Map인터페이스를 구현한 컬렉션 클래스(HashMap, SortedMap 등)는 키(Key)와 값(Value)을 쌍(pair)으로 저장하고 있기 때문에

   iterator()를 직접 호출할 수 없습니다. 그 대신 keySet()이나 entrySet()과 같은 반환 타입이 Set컬렉션인 메서드를 통해서

   키와 값을 각각 따로 Set의 형태로 얻어 온 후에 Set컬렉션에는 iterator()가 존재하므로 iterator()를 호출하여 Iterator를 얻을 수 있습니다.

 

- 다음은 ArrayList에 있는 요소들을 Iterator를 사용하여 읽어 오는 코드입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.edu.test;
 
import java.util.*;
 
public class test {
    public static void main(String[] args) {
        ArrayList<String> al = new ArrayList<String>();
        al.add("1");
        al.add("2");
        al.add("3");
        al.add("4");
        al.add("5");
        
        Iterator it = al.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());
        }
    }    
}
 
cs

<사진 1.3>

 

 다음은 결과 화면입니다.

 

<사진 1.3 결과 화면>

 

 

2. Enumeration 인터페이스

 

 - Enumeration인터페이스는 컬렉션 프레임웍이 만들어지기 이전에 사용하던 것으로 Iterator의 구버전이라고 생각하면 됩니다.

   이전 버전으로 작성된 소스와의 호환을 위해서 남겨 두고 있을 뿐이므로 가능하면 Enumeration대신 Iterator를 사용하도록 합시다.

 

 - 다음은 Enumeration인터페이스의 메서드입니다. Enumeration은 Iterator와 메서드 이름만 다를 뿐 기능은 같습니다.

 

<사진 1.4> Enumeration인터페이스의 메서드

 

 

3. ListIterator 인터페이스

 

 - ListIterator인터페이스는 Iterator를 상속받아서 기능을 추가한 것입니다. 컬렉션의 요소에 접근할 때 Iterator는 단방향으로만 이동할 수

   있지만 ListIterator는 양방향으로 이동이 가능하다는 장점이 있습니다. 또한 ArrayList나 LinkedList처럼 List인터페이스를 구현한 컬렉션

   클래스에서만 사용할 수 있습니다.

 

 - 다음은 ListIterator인터페이스의 메서드입니다.

 

<사진 1.5> ListIterator인터페이스의 메서드

 

 

 - 다음은 ListIterator인터페이스의 양방향 접근이 가능한 previous()메서드를 호출하여 이전 요소로 접근해보는 코드입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.edu.test;
 
import java.util.*;
 
public class test {
    public static void main(String[] args) {
        ArrayList<String> al = new ArrayList<String>();
        al.add("1");
        al.add("2");
        al.add("3");
        al.add("4");
        al.add("5");
        
        ListIterator li = al.listIterator(); // 순방향으로 진행하면서 요소를 읽어옵니다.
        
        while(li.hasNext()) {
            System.out.println(li.next());
        }
        System.out.println("-----------");
        
        while(li.hasPrevious()) { // 역방향으로 진행하면서 요소를 읽어옵니다.
            System.out.println(li.previous());
        }
        
        
    }    
}
cs

<사진 1.6> ListIterator인터페이스의 previous()메서드 사용

 

 - Iterator인터페이스는 단방향으로만 이동하기 때문에 컬렉션의 마지막 요소에 다다르면 더 이상 사용할 수 없지만,

   ListIterator인터페이스는 양방향으로 이동하기 때문에 각 요소간의 이동이 자유롭습니다. 다만 이동하기 전에 hasNext()메서드나

   hasPrevious()메서드를 호출하여 이동할 수 있는지 확인해야합니다.

반응형
반응형

 

1. Vector클래스란?

 

 - Vector 클래스는 ArrayList클래스와 같이 컬렉션 프레임웍에서 가장 많이 사용되는 컬렉션 클래스 일 것입니다.

   이 둘은List 인터페이스를 구현하기 때문에 List인터페이스의 특징인

   1. 저장순서를 유지하며

   2. 중복을 허용합니다.

   라는 특징을 가지고 있습니다.

 

 - Vector클래스의 기능을 개선 한 것이 ArrayList클래스입니다. Vector 클래스는 기존에 작성된 소스와의 호환성을 위해서 계속 남겨 두고 있을

   뿐이기 때문에 가능하면 Vector클래스보다 ArrayList클래스를 사용하는 것이 바람직하다고 할 수 있습니다.

   다음은 Vector클래스와 ArrayList클래스의 공통점과 차이점을 나타내는 표입니다.

 

<사진 1.1> Vector클래스와 ArrayList클래스의 비교

 

2. 벡터 생성하는 방법

 

 - 벡터를 생성할 때, Vector<E>의 E에 요소로 사용할 타입을 지정하면 됩니다. 예를 들어, 정수 값만 삽입 가능한 벡터를 만들고자 한다면

   다음과 같이 E 요소에 Integer를 지정하여 벡터를 생성하면 됩니다.

 

       Vector<Integer> v = new Vector<Integer>();

 

   만약 문자열만 삽입 가능한 벡터를 만들고 싶으면 다음과 같이 벡터를 생성하면 됩니다.

 

       Vector<String> v = new Vector<String>();.

 

   만일 Vector<E>에서 E 요소에 구체적인 타입을 지정하지 않는다면 컴파일러가 경고 메시지를 출력합니다.

 

3. Vector 클래스의 주요 메서드

 

 1) 벡터에 요소 삽입

 

   - add() 메서드를 사용하여 벡터의 끝이나 중간에 요소를 삽입할 수 있습니다. 다음은 정수 1, 2, 3을 순서대로 벡터에 삽입하는 코드입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
package com.edu.test;
 
import java.util.*;
 
public class test {
    public static void main(String[] args) {
        Vector<Integer> v = new Vector<Integer>();
        v.add(1);
        v.add(2);
        v.add(3);
    }    
}
cs

<사진 1.2> add() 메서드 사용

 

   - 벡터 v에는 Integer 외의 다른 타입의 객체를 삽입할 수 없습니다. 현재 제네릭이 Integer로 선언되어 있는데

     add() 메서드의 인자 값으로 정수형이 아닌 다른 타입을 삽입할 경우에는 오류가 발생합니다.

 

<사진 1.3>

 

   - 초기에 선언한 Integer 타입이 아닌 문자열 3을 삽입하였으니 빨간 줄이 생기면서 컴파일 오류가 발생하였습니다.

   - 참고로 벡터에는 null값을 삽입할 수 있기 때문에, 벡터를 검색할 때 null값이 존재할 수 있음을 염두해 두어야 합니다.

 

   - 다음은 add()메서드를 사용하여 벡터의 중간에 객체를 삽입해보겠습니다. 다음은 현재 벡터 v에 [1, 2, 3]이 저장 되어 있지만

     인덱스 1번 위치에 100 요소를 삽입해보는 코드입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.edu.test;
 
import java.util.*;
 
public class test {
    public static void main(String[] args) {
        Vector<Integer> v = new Vector<Integer>();
        v.add(1);
        v.add(2);
        v.add(3);
        
        v.add(1,100);
    }    
}
 
cs

<사진 1.4>

 

 - v.add(1,100); 는 인덱스 1의 위치에 정수 100을 삽입한다는 코드입니다. 다음은 결과 화면입니다.

 

<사진 1.4 결과 화면>

 

 - 결과를 보면 기존의 인덱스 1 위치에 있던 2와 그 뒤에 있던 3이 모두 한 자리씩 뒤로 이동했습니다.

   만약 벡터에 1개의 요소(인덱스 0의 위치)만 들어있는 상태인데 2의 위치에 요소를 삽입할 경우엔 예외가 발생합니다. 왜냐하면

   인덱스 1이 빈 공간이 되기 때문입니다.

 

 2) 벡터 내의 요소 알아내기

 

   - 벡터 내에 존재하는 요소를 알아내기 위해서는 get() 메서드와 elementAt() 메서드를 사용합니다. 다음은 get()메서드를 사용한 코드입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.edu.test;
 
import java.util.*;
 
public class test {
    public static void main(String[] args) {
        Vector<Integer> v = new Vector<Integer>();
        v.add(1);
        v.add(2);
        v.add(3);
        v.add(4);
        v.add(5);
        
        for(int i=0; i<v.size(); i++) {
            System.out.println(v.get(i));
        }
    }    
}
 
cs

<사진 1.5>

 

 - 벡터 v에 정수 1, 2, 3, 4, 5를 삽입했습니다. 벡터 v에 있는 모든 요소들을 순서대로 출력하기 위해 for문을 사용했습니다.

 - v.get(0)이 실행될 경우 벡터 v가 가리키고 있는 0번째 인덱스의 값을 추출합니다.

 

 - 다음은 현재 벡터 v의 상태를 그림으로 표현했습니다.

 

<사진 1.6>

 

 - 벡터 v는 0x100(임의의 주소로 아무렇게나 정한 것입니다)이라는 주소 값을 갖고 있는 위치를 가리키고 있습니다.

   현재 0x100위치에는

   0번 인덱스에 1,

   1번 인덱스에 2,

   2번 인덱스에 3,

   3번 인덱스에 4,

   4번 인덱스에 5라는 값을 저장하고 있습니다. 그래서 v.get(0)메서드를 호출할 경우 벡터 v가 가리키고 있는 0번째 인덱스 값인 1을 반환합니다.

   다음은 <사진 1.5> 코드의 결과 화면입니다.

 

<사진 1.5 결과 화면>

 

 - 벡터 v가 가리키고 있는 모든 요소들을 출력했습니다.

 

 3) 벡터에서 요소 삭제

 

 - 벡터 내의 임의의 인덱스에 있는 요소를 삭제할 수 있습니다. remove() 메서드를 사용하면 됩니다.

 

       v.remove(1); // 벡터 v가 가리키고 있는 1번째 인덱스의 값을 삭제하는 코드입니다.

 

 - 다음은 remove() 메서드를 사용한 코드입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.edu.test;
 
import java.util.*;
 
public class test {
    public static void main(String[] args) {
        Vector<Integer> v = new Vector<Integer>();
        v.add(1);
        v.add(2);
        v.add(3);
        v.add(4);
        v.add(5);
        
        v.remove(1);
        
        for(int i=0; i<v.size(); i++) {
            System.out.println(v.get(i));
        }
    }    
}
 
cs

<사진 1.7>

 

 - 현재 벡터 v는 정수 1, 2, 3, 4, 5를 배열로 저장하고 있는 상태에서 14번째 줄 코드에서 remove()메서드를 사용하여 인덱스 1 위치에 있는 요소를

   삭제하고 벡터 v가 저장하고 있는 모든 요소들을 출력하고자 합니다. 다음은 결과 화면입니다.

 

<사진 1.7 결과 화면>

 

 - 인덱스 1 위치에 있던 정수 2를 삭제 하여 뒤에 있던 요소들이 한 자리씩 앞으로 이동하였습니다.

 

 - 벡터의 모든 요소를 삭제하고자 한다면 v.removeAllElements(); 를 호출하면 됩니다.

반응형
반응형

 

 

배열은 연관된 data를 관리하기 위한 수단이다. 그런데 배열에는 몇가지 불편한 점이 있는데 그 중의 하나가 한번 정해진 배열의 크기는 변경할 수 없다는 점이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package hoony.tistory.java;
 
public class ArrayListTest {
    public static void main(String[] args) {
        String[] str = new String[3]; // 크키가 3인 String 배열을 선언했다.
        str[0= "one";
        str[1= "two";
        str[2= "three";
        str[3= "four"// 이 부분을 입력하면 오류가 발생한다.
        
        for(int i=0; i<str.length; i++) {
            System.out.println(str[i]);
        }
        
    }
}
 
cs

<코드1.1>

<코드1.1>처럼 처음에 선언한 배열의 크기를 벗어나면 오류가 발생한다. 이러한 불편함을 "컬렉션 프레임워크"를 사용하면 줄어든다.

 

아례의 예를 살펴보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package hoony.tistory.java;
 
import java.util.ArrayList;
 
public class ArrayListTest {
    public static void main(String[] args) {
        String[] str = new String[3];
        str[0= "one";
        str[1= "two";
        str[2= "three";
        
        for(int i=0; i<str.length; i++) {
            System.out.println(str[i]);
        }
        
        ArrayList al = new ArrayList();
        al.add("one");
        al.add("two");
        al.add("three");
        
        for(int i=0; i<al.size(); i++) {
            System.out.println(al.get(i));
        }
    }
}
 
cs

<코드1.2>

 

<코드1.1>처럼 배열은 크기를 한번 지정하면 크기보다 많은 수의 값을 저장할 수 없다는 것을 확인했다. 하지만

<코드1.2>를 보면 ArrayList는 크기를 미리 지정하지 않아도 많은 수의 값을 저장이 가능하다. 

 

배열을 사용할 때 배열의 길이를 구할 때는 .length를 사용했지만 ArrayList에서는 size() 메서드를 호출한다.

또한 특정한 값을 가져올 때 배열은 [인덱스 번호]를 사용했지만 ArrayList는 get(int index) 메서드를 호출한다. get() 메서드의 인자

으로 인덱스 번호를 입력하면 인덱스 값에 해당하는 값을 추출할 수 있다.

 

그런데 ArrayList를 사용할 때 주의해야 할 점이 있다.  <코드1.2>의 21~23 라인의 코드를 아래처럼 변경해보겠다.

 

1
2
3
4
5
for(int i=0; i<al.size(); i++) {
    String value = al.get(i);
    System.out.print(value);
}
 
cs

<코드1.3>

 

<코드1.3>을 컴파일하면 오류가 발생한다. 왜냐하면 ArrayList의 add() 메서드는 인자 값으로 어떤 형태의 값이 올지 알 수 없다.

즉, byte, short, int, long, char, stirng 등등 모든 타입이 입력 가능하다는 것이다. 그런데 get() 메서드를 사용하여 값을 추출한 후에

String 타입에 저장하기 때문에 오류가 발생한다.

( add() 메서드는 인자 값으로 모든 데이터의 조상인 Object 타입으로 데이터를 받는다. )

 

현 상황에서 오류를 해결하기 위한 방법은 아래 코드처럼 2가지 방법이 있다.

 

1
2
3
4
5
6
7
8
9
for(int i=0; i<al.size(); i++) {
    String value = (String)al.get(i); // 형변환
    System.out.print(value);
}
 
for(int i=0; i<al.size(); i++) {
    String value = al.get(i)+""// 문자열 더하기
    System.out.print(value);
}
cs

<코드1.4>

 

첫 번째 방법은 get() 메서드의 반환 값을 String타입으로 형변환 시켜주는 것이고 두 번째 방법은 get() 메서드의 반환 값과 ""(문자열)을 덧셈 연산을 해주는 것이다.(어떠한 타입 + String 타입 = String 타입이되기 때문이다.)

 

하지만 위의 방식은 예전의 방식이다. 이제는 아래와 같이 Generic(제너릭)을 사용해야 한다.

 

1
2
3
4
5
6
7
8
9
ArrayList<String> al = new ArrayList<String>();
al.add("one");
al.add("two");
al.add("three");
for(int i=0; i<al.size(); i++){
    String value = al.get(i);
    System.out.println(value);
}
 
cs

<코드1.5>

 

제너릭을 사용하면 ArrayList 내에서 사용할 데이터 타입을 인스턴스를 생성할 때 지정할 수 있기 때문에 데이터를

추출 할 때 굳이 형변환 또는 문자열 덧셈 연산을 하지 않아도 된다.

 

반응형

+ Recent posts