List 컬렉션 클래스
- 인스턴스 저장 순서가 유지된다. (나란히)
- 동일 인스턴스의 중복 저장을 허용한다.
- 공간의 크기를 신경쓰지 않아도 된다. (알아서 변경해줌)
클래스 | 자료구조 | 설명 |
ArrayList<E> | 배열 기반 자료구조 | 배열을 이용해 인스턴스를 저장 |
LinkedList<E> | 리스트 기반 자료구조 | 리스트를 구성해 인스턴스 저장 |
ArrayList
- 가장 많이 사용되는 컬렉션 클래스 중 하나이다.
- 장점
- 저장된 인스턴스의 참조가 빠르다
- 배열을 이용하기 때문에 인덱스를 이용해 배열 요소에 빠르게 접근할 수 있다.
- 단점
- 저장 공간을 늘리는 과정에서 시간이 비교적 많이 소요된다.
- 배열은 크기를 변경할 수 없는 인스턴스이므로, 크기를 늘리기 위해서는 더 큰 공간의 새로은 배열을 생성해
기존 배열에 있던 데이터를 새 배열에 옮겨야 하는 복잡한 과정을 거쳐야 한다.
- 배열은 크기를 변경할 수 없는 인스턴스이므로, 크기를 늘리기 위해서는 더 큰 공간의 새로은 배열을 생성해
- 인스턴스 삭제 과정에서 많은 연산이 필요할 수 있다. 따라서 느릴 수 있다.
- 저장 공간을 늘리는 과정에서 시간이 비교적 많이 소요된다.
class ListCollectionClass_ArrayList {
public static void main(String[] args) {
// 컬렉션 인스턴스 생성
List<String> arrList = new ArrayList<>();
// add() 메소드를 이용한 요소의 저장
arrList.add("cat");
arrList.add("dog");
arrList.add("pig");
// for문과 get() 메소드를 이용한 요소의 출력
for (int i = 0; i < arrList.size(); i++)
System.out.print(arrList.get(i) + " ");
System.out.println();
// remove() 메소드를 이용한 요소의 제거
arrList.remove(0);
// Enhanced for문과 get() 메소드를 이용한 요소의 출력
for (String e : arrList)
System.out.print(e + " ");
}
}
// 실행 결과
cat dog pig
dog pig
LinkedList
- LinkedList 클래스는 내부적으로 연결 리스트(linked list)를 이용하여 요소를 저장한다.
- 연결 리스트라는 것을 "칸칸이 연결된 화물 열차"라고 생각하면 쉽다.
즉, 인스턴스 저장은 열차 칸 하나 추가로 연결한 뒤 그 열차 칸에 인스턴스를 저장하는 것이며 인스턴스 삭제는 해당 인스턴스를 저장하고 있는 열차 칸을 삭제하는 것이다.
- 연결 리스트라는 것을 "칸칸이 연결된 화물 열차"라고 생각하면 쉽다.
- 장점
- ArrayList<E> 클래스와 달리 인스턴스의 저장 공간을 미리 마련해둘 필요가 없다.
- 저장 공간을 늘리는 과정이 간단하다.
- 저장된 인스턴스의 삭제 과정이 단순하다.
- 단점
- 저장된 인스턴스의 참조 과정이 배열에 비해 복잡하다. 따라서 느릴 수 있다.
class ListCollectionClass_LinkedList {
public static void main(String[] args) {
// 컬렉션 인스턴스 생성
List<String> lnkList = new LinkedList<>();
// add() 메소드를 이용한 요소의 저장
lnkList.add("cat");
lnkList.add("dog");
lnkList.add("pig");
// for문과 get() 메소드를 이용한 요소의 출력
for (int i = 0; i < lnkList.size(); i++)
System.out.print(lnkList.get(i) + " ");
System.out.println();
// remove() 메소드를 이용한 요소의 제거
lnkList.remove(0);
// Enhanced for문과 get() 메소드를 이용한 요소의 출력
for (String e : lnkList)
System.out.print(e + " ");
}
}
// 실행 결과
cat dog pig
dog pig
💡 단일 연결 리스트 & 이중 연결 리스트
- 단일 연결 리스트 : 다음 요소를 가리키는 참조만을 가지는 연결 리스트
- 이중 연결 리스트 : 이전 요소를 가리키는 참도도 가지는 연결 리스트
- 단일 연결 리스트는 요소의 저장과 삭제 작업이 다음 요소를 가리키는 참조만 변경하면 되므로 빠르게 처리될 수 있지만, 현재 요소에서 이전 요소로 접근하기가 매우 어렵다.
- 따라서 이전 요소를 가리키는 참조도 가지는 이중 연결 리스트가 좀 더 많이 사용된다.
순차적 접근 방법
컬렉션 클래스를 활용하는 데 있어서 저장된 모든 인스턴스들에 순차적으로 접근하는 것은 중요한 작업이다.
어떻게 컬렉션 클래스에 순차적으로 접근할 수 있는지 방법을 알아보자.
enhanced for문 사용
enhanced for문을 통한 순차적 접근의 대상이 되려면, 해당 컬렉션 클래스는 Iterable<T> 인터페이스를 구현해야 한다.
- public interface Collection<E> extends Iterable<E>
- 위와 같이 Collection 인터페이스는 Iterable 인터페이스를 상속한다. 따라서 Collection 인터페이스를 상속하는 ArrayList<E>, LinkedList<E>와 같은 클래스의 인스턴스를 대상으로 for-each문을 구성할 수 있다.
class Collection_EnhancedFor {
public static void main(String[] args) {
List<String> list = new LinkedList<>();
// 인스턴스 저장
list.add("cat");
list.add("dog");
list.add("pig");
// 전체 인스턴스 참조 (enhanced for문 사용)
for(String s : list)
System.out.print(s + " ");
System.out.println();
// 인스턴스 삭제
list.remove(0);
// 전체 인스턴스 참조
for(String s : list)
System.out.print(s + " ");
System.out.println();
}
}
// 실행 결과
cat dog pig
dog pig
반복자 사용
Iterator
- Iterable<E> 인터페이스의 Iterator() 추상메소드를 호출하면 반복자(Iterator)를 생성해 반환해준다.
- 반복자는 저장된 인스턴스들을 순차적으로 참조할 때 사용하는 인스턴스이다.
→ 반복자를 일종의 "지팡이"라고 생각하면 쉽다. 이 지팡이를 통해 저장된 인스턴스들을 가리키는 것이다.
메소드 종류 | 설명 |
E next() | 다음 인스턴스의 참조 값을 반환 |
boolean hasNext() | next 메소드 호출 시 참조 값 반환 가능 여부 확인 |
void remove() | next 메소드 호출을 통해 반환했던 인스턴스 삭제 |
class Collection_Iterator {
public static void main(String[] args) {
List<String> list = new LinkedList<>();
list.add("cat");
list.add("dog");
list.add("pig");
list.add("cat");
Iterator<String> itr = list.iterator(); // 반복자 획득(1)
// 반복자를 이용한 순차적 참조
while(itr.hasNext())
System.out.print(itr.next() + " ");
System.out.println();
itr = list.iterator(); // 반복자 획득(2)
// 모든 "cat" 삭제
String str;
while(itr.hasNext()) {
str = itr.next();
if(str.equals("cat"))
itr.remove();
}
itr = list.iterator(); // 반복자 획득(3)
// 삭제 후 결과 확인
while(itr.hasNext())
System.out.print(itr.next() + " ");
System.out.println();
}
}
// 실행 결과
cat dog pig cat
dog pig
enhanced for문을 통한 순차적 접근과 달리 반복자를 이용하면 반복 중간에 특정 인스턴스의 삭제가 가능하다.
while (itr.hasNext()) {
str = itr.next();
if(str.equals("cat"))
itr.remove(); // "cat"와 내용이 같은 인스턴스를 삭제
}
ListIterator (양방향 반복자)
- ListIterator<E> 인터페이스의 listIterator() 메소드 호출을 통해 양방향 반복자를 생성해 반환해준다.
- ListIterator<E> 인터페이스는 Iterator<E>를 상속한다.
- 양방향 반복자는 List<E> 인터페이스를 구현하는 클래스의 인스턴스들만 얻을 수 있다.
메소드 | 설명 |
E next() | 다음 인스턴스의 참조 값을 반환 |
boolean hasNext() | next 메소드 호출 시 참조 값 반환 가능 여부 확인 |
void remove() | next 메소드 호출을 통해 반환했던 인스턴스를 삭제 |
E previous() | next 메소드와 기능은 같고 방향만 반대 |
boolean hasPrevious() | hasNext 메소드와 기능은 같고 방향만 반대 |
void add(E e) | 인스턴스의 추가 |
void set(E e) | 인스턴스의 변경 |
class Collection_ListIterator {
public static void main(String[] args) {
List<String> list = Arrays.asList("cat", "dog", "pig", "cat");
list = new ArrayList<>(list);
ListIterator<String> litr = list.listIterator(); // 양방향 반복자 생성
String str;
// 왼쪽에서 오른쪽으로 이동을 위한 반복문
while(litr.hasNext()) {
str = litr.next();
System.out.print(str + " ");
if(str.equals("dog")) // "dog" 만나면 "dog2" 저장
litr.add("dog2");
}
System.out.println();
// 오른쪽에서 왼쪽으로 이동을 위한 반복문
while(litr.hasPrevious()) {
str = litr.previous();
System.out.print(str + " ");
if(str.equals("pig")) // "pig" 만나면 "pig2" 저장
litr.add("pig2");
}
System.out.println();
// 다시 왼쪽에서 오른쪽으로
for(Iterator<String> itr = list.iterator(); itr.hasNext();)
System.out.print(itr.next() + " ");
System.out.println();
}
}
// 실행 결과
cat dog pig cat
cat pig pig2 dog2 dog cat
cat dog dog2 pig2 pig cat
- 실행 결과를 통해 add() 메소드가 어느 위치에 인스턴스를 추가하는지 확인할 수 있다.
- next 호출 후에 add 호출하면, 앞서 반환된 인스턴스 뒤에 새 인스턴스가 삽입됨
- previout 호출 후에 add 호출하면, 앞서 반환된 인스턴스 앞에 새 인스턴스가 삽입됨
컬렉션 변환
배열 → ArrayList (asList)
- 배열과 ArrayList<E>는 특성이 유사하지만, 대부분의 경우 배열보다 ArrayList<E>가 더 좋다.
- 인스턴스의 저장과 삭제가 편하기 때문에
- 반복자를 사용할 수 있기 때문에
- 단, 배열처럼 선언과 동시에 초기화할 수 없어 초기에 무엇인가를 채워 넣는 일이 번거롭다.
- 하지만 이러한 문제는 asList()를 통해 해결할 수 있다.
List<String> list = Arrays.asList("cat", "dog", "pig", "monkey");
- 인자로 전달된 인스턴스들을 저장한 컬렉션 인스턴스의 생성 및 반환
- 이렇게 만들어진 컬렉션 인스턴스는 추가 및 삭제가 불가능 (Imutable)
- 따라서 다음 생성자를 기반으로 ArrayList<E>를 생성해야한다.
// ArrayList 생성자
class ArrayList<E> {
public ArrayList(Collection<? extends E> c) {...}
}
- Collection<E>를 구현한 컬렉션 인스턴스를 인자로 전달받는다.
- 그리고 E는 인스턴스 생성 과정에서 결정되므로 무엇이든 될 수 있다.
- 또한 extends로 상한 제한했으므로, 매개변수 c로 전달된 컬렉션 인스턴스에서는 꺼내기(get)만 가능하다.
List<String> list = Arrays.asList("cat", "dog", "pig", "monkey");
list = new Arraylist<>(list);
더보기
class Collection_AsList {
public static void main(String[] args) {
List<String> list = Arrays.asList("cat", "dog", "pig", "cat");
list = new ArrayList<>(list);
// for문 기반의 반복자 획득과 순차적 참조
for(Iterator<String> itr = list.iterator(); itr.hasNext();)
System.out.print(itr.next() + " ");
System.out.println();
// "cat"을 모두 삭제하기 위한 반복문
for(Iterator<String> itr = list.iterator(); itr.hasNext();) {
if(itr.next().equals("cat"))
itr.remove();
}
for(Iterator<String> itr = list.iterator(); itr.hasNext();)
System.out.print(itr.next() + " ");
System.out.println();
}
}
// 실행 결과
cat dog pig cat
dog pig
ArrayList → LinkedList
class Collection_Conversion {
public static void main(String[] args) {
List<String> list = Arrays.asList("cat", "dog", "pig", "cat");
list = new ArrayList<>(list);
// ArrayList<E> 인스턴스의 순차적 접근
for(Iterator<String> itr = list.iterator(); itr.hasNext();)
System.out.print(itr.next() + " ");
System.out.println();
// ArrayList<E> 인스턴스 기반으로 LinkedList<E> 인스턴스 생성
list = new LinkedList<>(list);
// LinkedList<E> 인스턴스의 순차적 접근
for(Iterator<String> itr = list.iterator(); itr.hasNext();)
System.out.print(itr.next() + " ");
System.out.println();
}
}
// 실행 결과
cat dog pig cat
cat dog pig cat
Reference
https://bangu4.tistory.com/204?category=1003336
http://www.tcpschool.com/java/java_collectionFramework_list
'☕ Java > 이론' 카테고리의 다른 글
[Java] 열거형 (enum) (0) | 2022.01.26 |
---|---|
[Java] 컬렉션 기반 알고리즘 (sort, binarySearch, copy) (0) | 2022.01.25 |
[Java] Queue 컬렉션 클래스 (0) | 2022.01.25 |
[Java] Set 컬렉션 클래스 (0) | 2022.01.25 |
[Java] Map 컬렉션 클래스 (0) | 2022.01.25 |
[Java] 컬렉션 프레임워크 (0) | 2022.01.18 |
[Java] 제네릭3 (와일드 카드) (0) | 2022.01.17 |
[Java] 제네릭2 (상속, 제네릭 인터페이스) (0) | 2022.01.14 |