-
[Java] 컬렉션 프레임워크 - ListCSE/Java 2015. 9. 12. 10:32
컬렉션 프레임 워크는 여러 절로 구성되어 있습니다.
2. List 컬렉션
List는 객체를 일렬로 늘어놓은 구조를 가지고 있습니다.
객체를 인덱스로 관리하기 때문에 객체를 저장하면 자동 인덱스가 부여되고 인덱스로 객체를 검색, 삭제할 수 있는 기능을 제공합니다.
List 컬렉션은 객체 자체를 저장하는 것이 아니라 다음 그림과 같이 객체의 번지를 참조합니다.
동일한 객체를 중복 저장할 수 있는데, 이 경우 동일한 번지가 참조됩니다.
null도 저장이 가능한데, 이 경우 해당 인덱스는 객체를 참조하지 않습니다.
List 컬렉션에는 ArrayList, Vector, LinkedList 등이 있는데, 다음은 List 컬렉션에서 공통적으로 사용 가능한 List 인터페이스의 메소드들입니다.
인덱스로 객체를 관리하기 때문에 인덱스를 파라미터로 갖는 메소드가 많습니다.
앞의 표에서 메소드의 파라미터 타입과 리턴 타입에 E라는 타입 파라미터가 있는데, 이것은 List 인터페이스가 제네릭 타입이기 때문입니다.
구체적인 타임은 구현 객체를 생성할 때 결정됩니다.
객체 추가는 add() 메소드를 사용하고, 객체를 찾아올 때는 get() 메소드를 사용합니다. 그리고 객체 삭제는 remove() 메소드를 사용합니다.
다음은 List 컬렉션에 저장되는 구체적인 타입을 String으로 정해놓고 추가, 삽입, 찾기 그리고 삭제를 하는 방법을 보여줍니다.
123456List<String> list = ...;list.add("Jackie");list.add(1, "Park");String str = list.get(1);list.remove(0);list.remove("Park");cs 만약 전체 객체를 대상으로 하나씩 반복해서 저장된 객체를 얻고 싶다면 다음과 같이 for문을 사용할 수 있습니다.
123456List<String> list = ...;for (int i = 0; i < list.size(); i++) {String str = list.get(i);}cs 인덱스 번호가 필요 없다면 향상된 for 문을 이용하는 것이 더욱 편리합니다.
1234for (String str : list) {}cs 2.1 ArrayList
ArrayList는 List 인터페이스의 구현 클래스로, ArrayList에 객체를 추가하면 객체가 인덱스로 관리됩니다.
일반 배열과 ArrayList는 인덱스로 객체를 관리한다는 점에서는 유사하지만, 큰 차이점을 가지고 있습니다.
배열은 생성할 때 크기가 고정되고 사용 중에 크기를 변경할 수 없지만, ArrayList는 저장 용량(capacity)을 초과한 객체들이 들어오면 자동적으로 저장 용량이 늘어난다는 점입니다.
ArrayList를 생성하기 위해서는 저장할 객체 타입을 타입 파라미터로 표기하고 기본 생성자를 호출하면 됩니다. 예를 들어 String을 저장하는 ArrayList는 다음과 같이 생성할 수 있습니다.
12List<String> list = new ArrayList<String>();cs 기본 생성자로 ArrayList 객체를 생성하면 내부에 10개의 객체를 저장할 수 있는 초기 용량을 가지게 됩니다.
저장되는 객체 수가 늘어나면 용량이 자동으로 증가하지만, 처음부터 용량을 크게 잡고 싶다면 용량의 크기를 파라미터로 받는 생성자를 이용하면 됩니다.
12List<String> list = new ArrayList<String>(30);cs * ArrayListExam.java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748package collection;import java.util.ArrayList;import java.util.List;public class ArrayListExam {public static void main(String[] args) {List<String> list = new ArrayList<String>();list.add("Java");list.add("JDBC");list.add("JTBC");list.add("Servlet/JSP");list.add(2, "Database");list.add("iBATIS");list.add("C");list.add("C#");int size = list.size();System.out.println("총 객체 수: " + size);System.out.println();String skill = list.get(2);System.out.println("2: " + skill);System.out.println();for (int i = 0; i < list.size(); i++) {String str = list.get(i);System.out.println(i + ": " + str);}System.out.println();list.remove(2);list.remove(2);list.remove("iBATIS");for (int i = 0; i < list.size(); i++) {String str = list.get(i);System.out.println(i + ": " + str);}}}cs ArrayList를 생성하고 런타임 시 필요에 의해 객체들을 추가하는 것이 일반적이지만, 고정된 객체들로 구성된 List를 생성할 때도 있습니다.
이러한 경우에는 Arrays.asList(T.. a) 메소드를 사용하는 것이 간편합니다.
12List<T> list = Arrays.asList(T... a);cs T 타입 파라미터에 맞게 asList() 의 파라미터를 순차적으로 입력하거나, T[] 배열을 파라미터로 주면 됩니다. 다음은 고정된 String 객체를 요소로 갖는 ArrayList 객체를 생성합니다.
* ArraysAsListExam.java
1234567891011121314151617181920212223242526package collection;import java.util.Arrays;import java.util.List;public class ArraysAsListExam {public static void main(String[] args) {List<String> strList = Arrays.asList("Jackie", "Andy", "Park");for (String name : strList) {System.out.println(name);}System.out.println();List<Integer> intList = Arrays.asList(1, 2, 5, 7);for (int num : intList) {System.out.println(num);}}}cs 2.2 Vector
Vector는 ArrayList와 동일한 내부 구조를 가지고 있습니다. Vector를 생성하기 위해서는 저장할 객체 타입을 타입 파라미터로 표기하고 기본 생성자를 호출하면 됩니다.
12List<E> list = new Vector<E>();cs ArrayList와 다른 점은 Vector는 동기화된(synchronized) 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 이 메소드들을 실행할 수 없고, 하나의 스레드가 실행을 완료해야만 다른 스레드를 실행할 수 있습니다.
그래서 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제할 수 있습니다.
다음은 Vector를 이용해서 Board 객체를 추가, 삭제, 검색하는 예제입니다.
* VectorExam.java
12345678910111213141516171819202122232425package collection;import java.util.List;import java.util.Vector;public class VectorExam {public static void main(String[] args) {List<Board> list = new Vector<Board>();for (int i = 1; i <= 5; i++) {list.add(new Board("제목" + i, "내용" + i, "글쓴이" + i));}list.remove(2);list.remove(3);for (Board board : list) {System.out.println(board.subject + "\t" + board.content + "\t" + board.writer);}}}cs * Board.java
12345678910111213141516171819202122232425262728293031323334353637383940package collection;public class Board {String subject;String content;String writer;public Board(String subject, String content, String writer) {this.subject = subject;this.content = content;this.writer = writer;}public String getSubject() {return subject;}public void setSubject(String subject) {this.subject = subject;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public String getWriter() {return writer;}public void setWriter(String writer) {this.writer = writer;}}cs 2.3 LinkedList
LinkedList는 List 구현 클래스이므로 ArrayList와 사용 방법은 똑같지만 내부 구조는 완전 다릅니다.
ArrayList는 내부 배열에 객체를 저장해서 인덱스로 관리하지만, LinkedList는 인접 참조를 링크해서 체인처럼 관리합니다.
LinkedLIst에서 특정 인덱스의 객체를 제거하면 앞뒤 링크만 변경되고 나머지 링크는 변경되지 않습니다.
특정 인덱스에 객체를 삽입할 때에도 마찬가지입니다. ArrayList는 중간 인덱스의 객체를 제거하면 뒤의 객체는 인덱스가 1씩 앞으로 당겨진다고 했습니다.
그렇기 때문에 빈번한 객체 삭제와 삽입이 일어나는 곳에서는 ArrayList보다 LinkedList가 좋은 성능을 발휘합니다.
LinkedList를 생성하기 위해서는 저장할 객체 타입을 타입 파라미터(E)에 표기하고 기본 생성자를 호출하면 됩니다.
LinkedList가 처음 생성될 때에는 어떠한 링크도 만들어지지 않기 때문에 내부는 비어 있다고 보면 됩니다.
12List<E> list = new LinkedList<E>();cs 다음 예제는 ArrayList와 LinkedList에 10000개의 객체를 삽입하는데 걸린 시간을 측정한 것입니다.
0번 인덱스에 String 객체를 10000번 추가하기 위해 List 인터페이스의 add(int index, E element) 메소드를 이용했습니다.
* LinkedListExam.java
123456789101112131415161718192021222324252627282930313233343536373839404142package collection;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;public class LinkedListExam {public static void main(String[] args) {List<String> arrList = new ArrayList<String>();List<String> linkedList = new LinkedList<String>();long startTime;long endTime;long runTime;startTime = System.nanoTime();for (int i = 0; i < 10000; i++) {arrList.add(0, String.valueOf(i));}endTime = System.nanoTime();runTime = endTime - startTime;System.out.println("ArrayList 걸린시간: " + runTime + " ns");startTime = System.nanoTime();for (int i = 0; i < 10000; i++) {linkedList.add(0, String.valueOf(i));}endTime = System.nanoTime();runTime = endTime - startTime;System.out.println("LinkedList 걸린시간: " + runTime + " ns");}}cs 끝에서부터(순차적으로) 추가/삭제하는 경우는 ArrayList가 빠르지만, 중간에 추가 또는 삭제할 경우는 앞뒤 링크 정보만 병경하면 되는 LinkedList가 더 빠릅니다.
* 이 포스트은 서적 '이것이 자바다' 를 참고하여 작성한 포스트입니다.
'CSE > Java' 카테고리의 다른 글
[Java] 컬렉션 프레임워크 - 검색 기능을 강화시킨 컬렉션 (0) 2015.09.14 [Java] 컬렉션 프레임워크 - Map 컬렉션 (0) 2015.09.13 [Java] 컬렉션 프레임워크 - Set 컬렉션 (0) 2015.09.13 [Java] 컬렉션 프레임워크 - Intro (0) 2015.09.11 [Java] 스트림과 병렬 처리 - 수집, 병렬 처리 (0) 2015.09.10 [Java] 스트림과 병렬 처리 - 루핑, 매칭, 집계 (0) 2015.09.10