▶ List 인터페이스
- 리스트(List)는 순서를 가지는 원소들의 모임으로 중복된 원소를 가질 수 있다.
- 위치(index)를 사용하여 원소에 접근한다는 점이 배열과 동일하다.
- 리스트에 들어 있는 원소들의 인덱스는 0부터 시작한다.
- 리스트 인터페이스는 ArrayList, LinkedList, Vector 등의 클래스에 의하여 구현된다. Vector 클래스는 이전 버전에서도 있었던 것으로 멀티 스레드 환경에서도 사용할 수 있도록 동기화되어 있다.
▶ ArrayList
- 저장되는 데이터의 개수에 따라 자동적으로 크기가 변경된다.
- 가변 크기의 배열(Dynamic Array)이라고도 불린다.
- 원소가 삭제되면 그만큼 크기를 줄이게 된다.
- 타입 매개변수를 가지는 제네릭 클래스로 제공된다.
ArrayList<String> arrList = new ArrayList<String>(); //타입 매개변수 지정
[기본 연산]
데이터 저장 시 Collection 인터페이스의 add() 메소드를 사용한다.
arrList .add(“Hello”); // index0 : Hello
arrList .add(“World”); // index1 : World
arrList .add(“Good!”); // index2 : Good!
기존의 데이터가 들어 있는 위치를 지정하여 add()를 호출하면, 그 위치에 삽입된다.
arrList .add(1, “Yeah~”); // index0 : Hello, index1 : Yeah~, index2 : World, index 3: Good!
특정한 위치에 있는 원소를 바꾸려면 set() 메소드를 사용
arrList .set(2, “Nice”); // index0 : Hello, index1 : Yeah~, index2 : Nice, index 3: Good!
데이터를 삭제하려면 remove() 메소드 사용
arrList .remove(3); // index0 : Hello, index1 : Yeah~, index2 : Nice
저장된 객체 가져오려면 get() 메소드 사용
String s = arrList .get(1); // “Yeah~” 반환
현재 저장된 원소의 개수를 얻으려면 size() 메소드 사용 (단, 범위를 벗어나는 인덱스를 사용하면 예외가 발생한다.)
System.out.println("총 원소 개수 : " + arrList.size()); // 출력 결과 → 총 원소 개수 : 3
[추가 연산]
특정 데이터의 위치를 알려면 indexOf() 메소드 사용
int index = arrList.indexOf(“Yeah~”); // 1이 반환된다.
단, 중복된 데이터는 맨 처음에 있는 데이터의 위치가 반환된다.
ArrayList<String> arrList2 = new ArrayList<>();
arrList2 .add(“Hello”); // index0 : Hello
arrList2 .add(“Hello”); // index1 : Hello
arrList2 .add(“Good!”); // index2 : Good!
System.out.println(arrList2.indexOf("Hello"); // 0이 반환된다.
탐색을 반대방향으로 하려면 lastIndexOf() 메소드를 사용 (끝에서부터 탐색한다.)
ArrayList<String> arrList2 = new ArrayList<>();
arrList2 .add(“Hello”); // index0 : Hello
arrList2 .add(“Hello”); // index1 : Hello
arrList2 .add(“Good!”); // index2 : Good!
System.out.println(arrList2.lastIndexOf("Hello"); // 1이 반환된다.
- 참고 : 배열, ArrayList, 문자열 객체의 크기를 알아내는 방법은 서로 다르다.
배열 : array.length
ArrayList : arrayList.size()
문자열 : string.length()
- ArrayList에 있는 원소에 접근하는 또 다른 방법은 반복자(iterator)를 사용하는 것이다. 반복자는 특별한 타입의 객체로 컬렉션의 원소들을 접근하는 것이 목적이다. 또한 모든 컬렉션에서 반복자를 적용할 수 있다. 반복자는 java.util 패키지에 정의되어 있는 Iterator 인터페이스를 구현하는 객체이다. 아래는 Iterator 인터페이스에서 제공하는 메소드이다. 원래 3개의 메소드만 제공한다.
메소드 | 설명 |
hasNext() | 아직 방문하지 않은 원소가 있으면 true를 반환 |
next() | 다음 원소를 반환 |
remove() | 최근에 반환된 원소를 삭제한다. |
- 반복자를 사용하려면 아래와 같이 iterator() 메소드를 호출하여 반복자 객체를 얻어야한다.
Iterator iterator = arrList.iterator(); //반복자 객체 얻기
...
while(iterator.hasNext()) {
s = (String) s.next(); //반복자는 Object 타입을 반환하므로 캐스팅해야 한다.
System.out.println(s);
}
출력 결과 :
Hello
Yeah~
Nice
- 반복자 사용을 보다 간편하게 한 것은 자바 버전 1.5부터 도입된 for-each 루프이다.
▶ LinkedList
- 연결 리스트(LinkedList)는 각 원소를 링크로 연결한다. 따라서 각 원소들은 이전 원소를 가리키는 링크와 다음 원소를 가리키는 링크를 저장한다. 이처럼 자바에서는 모든 연결 리스트가 이중 연결 리스트로 구현되어 있다.
- 중간에 빈번하게 원소(데이터)의 삽입과 삭제가 이루어지는 경우 연결 리스트는 링크만 수정하면 되기 때문에 ArrayList보다 더 효율적이다. LinkedList는 위와 같은 연산에서는 일정한 시간이 걸리나 ArrayList에서는 원소의 개수에 비례하는 시간이 소요된다.
- 단, 위치(index)를 가지고 원소를 접근하는 연산은 ArrayList보다 시간이 더 많이 걸린다. 즉, 위치(인덱스) 기반의 접근이 많다면 ArrayList가 더 낫다. 사용 방법은 ArrayList와 유사하다.
- LinkedList 예제
import java.util.*; public class LinkedListTest { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<String>(); linkedList.add(“Hello”); linkedList.add(“Nice”); linkedList.add(“Yeah!!”); linkedList.add(“Cheer”); linkedList.add(“Up!!”); for(int i = 0; i <linkedList.size(); i++) { System.out.println(linkedList.get(i)); } } }
- 연결 리스트도 반복자를 지원한다. 연결 리스트도 리스트이기 때문에 리스트에서 사용하기 편리한 반복자가 제공되는데, 바로 ListIterator이다.
interface ListIterator<E> extends Iterator<E> {
...
//두 개의 메소드가 제공되며, 리스트를 역순으로 방문하는 경우에 사용된다.
E previous();
boolean hasPrevious();
...
}
- 배열을 리스트로 변경하는 방법은 Arrays.asList() 메소드를 사용하는 것이다.
이 메소드는 배열을 받아서 리스트 형태로 반환한다.
리스트를 변경하면 배열도 변경되며 그 역도 성립한다.
리스트의 크기는 배열과 같고 변경이 불가능하다.
배열을 컬렉션이나 리스트를 받는 메소드에 매개변수로 넘기는 것을 허용한다.
고정된 크기의 리스트를 원하는 경우에 어떤 일반적인 리스트 구현보다 효율적이다.
List<String> list = Arrays.asList(new String[100]);
▶ Vector 클래스
- Vector 클래스는 java.util 패키지에 있는 컬렉션의 일종으로 “가변 크기의 배열(dynamic array)”을 구현하고 있다.
- 배열의 원소 개수가 늘어나면 자동으로 배열의 크기가 늘어난다.
- 어떤 타입의 객체라도 저장할 수 있다. 기초 자료형 역시 오토박싱 기능을 이용하여 객체로 변환되어 저장된다.
- 제네릭도 지원하므로 생성 시 new String<T>의 형태로 선언하면 T 타입의 객체만을 저장하는 Vector를 생성할 수 있다.
자주 사용되는 메소드 | |
boolean add() | Vector 객체에 요소를 추가한다. |
boolean add(int index, Object object) | 정해진 위치에 요소를 추가한다. |
Object get(int index) | 해당 위치의 요소를 추출한다. 단, 추출 시 캐스팅해야 한다. |
int size() | 현재 요소들의 개수를 반환한다. |
- Vector 예제
import java.util.Vector; public class VectorTest { public static void main(String[] args) { Vector v = new Vector(); v.add("안녕하세요"); v.add(new Integer(20)); v.add(400); System.out.println("vector size : " + v.size()); for (int i = 0; i < v.size(); i++) { System.out.println("vector element " + i + " : " + v.get(i)); } String s = (String) v.get(0); //추출 시 형변환 필수 ! } }
[출력 결과]
'Programming Language > JAVA' 카테고리의 다른 글
40. Queue - 큐, FIFO, 우선순위 큐 (0) | 2017.07.24 |
---|---|
39. Set, HashSet, TreeSet, LinkedHashSet - 집합 (0) | 2017.07.24 |
37. Collection, Vector - 컬렉션, Vector 클래스, Collection 인터페이스 (0) | 2017.07.23 |
36. Generic - 제네릭 클래스, 제네릭 프로그래밍 (9) | 2017.07.23 |
35. Exception, try-catch-finally - 예외, 예외 처리 (0) | 2017.07.23 |