List 인터페이스를 구현한 클래스로, ArrayList, LinkedList, Vector, Stack이 있다. 요소의 저장 순서가 유지되고, 같은 요소의 중복 저장이 허용되는 것이 특징이다.
메서드 | 설명 |
---|---|
void add(int index, E element) boolean addAll(int index, Collcetion<E> c) | 지정된 위치에 특정 객체나 컬렉션에 포함된 모든 객체들을 추가 해당 index부터 기존 객체들은 뒤로 밀려남 |
E get(int index) | 해당 index의 객체 반환 |
int indexOf(Object o) | 지정된 객체가 처음으로 나오는 index를 반환 해당 객체가 없으면 -1 반환 |
int lastIndexOf(Object o) | 지정된 객체가 마지막으로 나오는 index를 반환 해당 객체가 없으면 -1 반환 |
ListIterator listIterator() ListIterator listIterator(int index) | List 객체에 접근할 수 있는 ListIterator를 반환 (index를 지정해주면 iterator의 위치가 해당 index로 정해짐) |
E remove(int index) | 지정된 index에 있는 객체를 삭제하고 삭제된 객체 반환 |
E set(int index, Object eleement) | 지정된 index에 새로운 객체를 저장 |
void sort(Comparator c) | 지정된 Comparator로 정렬 |
List<E> subList(int fromInmdex, int toIOndex) | 지정된 범위의 객체 반환 |
List<E>의 자식 클래스로, 내부적으로 배열을 이용한다.
배열을 이용하기 때문에 인덱스를 이용해 각 요소에 빠르게 접근할 수 있다는 장점이 있다.
그러나 크기를 늘리기 위해서는 새로운 배열을 생성하고 요소들을 옮기는 과정을 거쳐야 하기 때문에 추가 및 삭제 작업은 느리다는 단점이 있다. 새로운 배열을 생성하는 횟수를 줄이기 위해 미리 큰 배열을 생성하면, 메모리가 낭비된다. 단, 배열의 끝부분에서 객체를 추가하거나 삭제하는 작업의 경우 기존의 객체들을 옮기는 작업이 필요하지 않기 때문에 빠르다.
개발자가 생성자에 매개변수를 따로 넣어주지 않는 경우 초기 capacity는 10으로 설정되어 있다. 해당 capacity를 초과하지 않는 선에서 add를 할 경우 새 객체가 들어갈 index에서부터 기존의 객체들이 하나씩 뒤로 밀려나고, 해당 index에 새 객체가 들어가는 방식으로 동작한다. capacity를 초과하게 되는 경우 새로운 배열을 만들어 기존 객체들과 새 객체들을 담아놓고, 새로 만든 배열을 참조하는 방식으로 동작한다.
제거된 객체보다 뒤에 있는 객체들이 한칸씩 앞당겨지는 방식으로 동작한다. 객체가 담기지 않는 자리는 null로 처리된다.
ArrayList<Integer> arrList = new ArrayList<Integer>();
// add() 메소드를 이용한 요소의 저장
arrList.add(40);
arrList.add(20);
arrList.add(30);
arrList.add(10);
// for 문과 get() 메소드를 이용한 요소의 출력
for (int i = 0; i < arrList.size(); i++) {
System.out.print(arrList.get(i) + " ");
}
// remove() 메소드를 이용한 요소의 제거
arrList.remove(1);
// Enhanced for 문과 get() 메소드를 이용한 요소의 출력
for (int e : arrList) {
System.out.print(e + " ");
}
// Collections.sort() 메소드를 이용한 요소의 정렬
Collections.sort(arrList);
// iterator() 메소드와 get() 메소드를 이용한 요소의 출력
Iterator<Integer> iter = arrList.iterator();
while (iter.hasNext()) {
System.out.print(iter.next() + " ");
}
// set() 메소드를 이용한 요소의 변경
arrList.set(0, 20);
for (int e : arrList) {
System.out.print(e + " ");
}
// size() 메소드를 이용한 요소의 총 개수
System.out.println("리스트의 크기 : " + arrList.size());
ArrayList와 사용할 수 있는 메서드가 거의 동일하다. 그러나 차이점이 있는데, 바로 데이터의 추가, 삭제 등의 작업을 수행하는 메서드가 동기화 메서드라는 점이다. 그래서 여러 스레드에서 Vector에 접근하더라도 안전하게 작업을 수행할 수가 있다. 그러나 ArrayList를 다루더라도 개발자가 따로 동기화 메서드를 선언해서 사용하면 그만이므로 ArrayList를 사용하는 것이 권장된다.
내부적으로 이중 연결 리스트를 구현한 클래스이다. 그래서 각 객체는 자신과 인접한 객체와 서로 연결된다. 객체 삽입과 삭제 시 인접한 객체들의 링크만 바꾸면 되기 때문에 비순차적인 삽입, 삭제 작업이 빠르다는 장점이 있다. 그러나 index를 통하여 객체에 접근할 경우 앞에서 부터 index를 세며 순차적으로 넘어가기 때문에 접근 속도가 느리다는 단점이 있다.
List 컬렉션 클래스도 배열처럼 향상된 for문을 사용할 수 있다.
List<String> list = new ArrayList<>();
list.add("111");
list.add("222");
for(String i: list){
System.out.println(i);
}
ArrayList, HashSet, HashMap 등의 메서드는 동기화된 메서드가 아니라서 여러 스레드에서 접근할 때 문제가 발생할 수가 있다. Collections라는 클래스에서는 synchronizedXXX라는 이름의 메서드들을 제공하고 있다. 이 메서드에서 반환된 Collection의 메서드는 동기화되어 있다.
List<T> list = Collections.synchronizedList(new ArrayList<T>());
Set<E> set = Collections.synchronizedSet(new HashSet<E>());
Map<K, V> map = Collections.synchronizedMap(new HashMap<K, V>());