티스토리 뷰

Programming Language/JAVA

자바 컬렉션

광식'S Story 2009. 2. 19. 18:03

자바 컬렉션

1. 서론

 

1.1 알아두기 : java.util 패키지의 구성

- 컬렉션 프레임웍(Collection Framework) : 다수의 데이터를 쉽게 처리할 수 있는 표준화된 방법을 제공

하는 클래스들

- 유용한 클래스 : 알아두면 좋은 자주 쓰이는 클래스들

- 형식화 클래스 : 데이터를 표준화도니 형식으로 출력하는데 도움을 주는 클래스들

 

1.2 컬렉션 프레임웍

* 컬렉션 : 다수의 데이터 즉, 데이터 그룹

* 프레임웍 : 표준화된 프로그래밍 방식

* 컬렉션 클래스 : 다수의 데이터를 저장할 수 있는 클래스

 

--> 컬렉션 프레임웍 : 데이터군을 저장하는 클래스들을 표준화한 설계. JDK1.2 이전까지는 Vector,

Hashtable, Properties 와 같은 컬렉션 클래스들을 서로 다른 각자의 방식으로 처리해야 했으나,

JDK1.2 부터는 컬렉션프레임웍이 등장하면서 다양한 종류의 컬렉션 클래스가 추가되고 모든 컬렉션

클래스를 표준화도니 방식으로 다룰 수 있도록 체계화되었다.

 

 

2. 본론

 

2.1 컬렉션 프레임웍의 핵심 인터페이스 - List, Set, Map 

 

 

2.2 컬렉션 프레임웍의 핵심 인터페이스와 특징

인터페이스

특 징

List

순서가 있는 데이터의 집합. 데이터의 중복을 허용한다. 저장순서에 의해 접근.

예) 대기자 명단

구현클래스 : ArrayList, LinkedList, Stack, Vector 등

Set

순서를 유지하지 않는 데이터의 집합. 데이터의 중복을 허용하지 않는다.

예) 양의 정수집합, 소수의 집합 등

구현클래스 : HashSet, TreeSet 등

Map

키(key)와 값(value)의 쌍(pair)으로 이루어진 데이터의 집합

순서는 유지되지 않으며, 키는 중복을 허용하지 않고, 값은 중복을 허용한다.

키에 의한 데이터 접근 가능

예) 우편번호, 지역번호(전화번호)

구현클래스 : HashMap, TreeMap, Hashtable, Properties 등

 

2.3 Collection 인터페이스 : 최상위 인터페이스

메소드

설명

int size()

컬렉션에 저장된 객체의 개수 반환

boolean isEmpty()

컬렉션이 비어있는지 확인

boolean add(E o)

지정된 객체를 컬렉션에 추가

boolean remove(O o)

지정된 객체를 삭제

void clear()

컬렉션의 모든 객체를 삭제

Object[] toArray()

컬렉션에 있는 요소를 객체배열로 바꾼다.

 

2.4 List 인터페이스

메소드

설명

int indexOf(O o)

지정된 객체의 위치를 반환(첫번째 요소부터 순방향)

int lastIndexOf(O o)

지정된 객체의 위치를 반환(마지막 요소부터 역방향)

E get(int index)

index 위치의 객체를 반환

E set(int index, E element)

지정된 위치(index)에 객체(element)를 저장(덮어쓰기)

void add(int index, E element)

주어진 index에 객체 저장.(밀어내기)

E remove(int index)

index 위치의 객체 지우고 삭제된 객체 반환

 

2.5 Set 인터페이스 : 생략

 

2.6 Map 인터페이스

메소드

설명

int size()

저장된 key-value쌍의 개수 반환

boolean isEmpty()

Map 이 비어있는지 확인

V put(K key, V value)

Map 에 있는 value객체를 key 객체에 연결하여 저장

V get(O key)

지정된 key객체에 대응하는 value객체를 찾아서 반환

V remove(O key)

지정한 key객체와 일치하는 key-value 객체를 삭제

boolean containsKey(O key)

key 객체와 일치하는 key 객체가 있는지 확인

boolean containsValue(O value)

value 객체와 일치하는 value객체가 있는지 확인

 

 

2.7 ArrayList 와 Vector 클래스

<공통점>

- 컬렉션 프레임웍에서 가장 많이 사용되는 컬렉션 클래스

- List 인터페이스를 구현

- 저장 순서가 유지되고 중복을 허용

- 데이터의 저장 공간으로 배열을 사용한다

- 다른종류의 데이터형을 가진 데이터요소를 가질 수 있음

- 가득 차게 되면 자동으로 저장 영역을 늘려줌

- 오토박싱 / 언박싱. 기본데이터형 변수를 저장하는 것도 가능

- 시퀸스(Sequence) 데이터 구조 : 순차적인 인덱스값에 대한 위치로 접근

- 인덱스값을 이용해서 자료구조의 임의의 지점에서 저장 및 접근이 가능

 

<차이점>

- Vector 는 멀티쓰레드에 대한 동기화가 되어 있으나, ArrayList 는 동기화 처리가 되어 있지 않다.

 

** 동기화(Synchronization) : 멀티쓰레드 프로그래밍에서는 하나의 객체를 여러 쓰레드가 동시에

접근할 수 있기 때문에 데이터의 일관성을 유지하기 위해서는 동기화가 필요하다. 그러나, 멀티

쓰레드 프로그래밍이 아닌 경우에는 불필요한 기능이 되어 오히려 성능을 떨어뜨리는 요인이

된다. 그래서 새로 추가된 ArrayList 와 HashMap 같은 컬렉션에서는 동기화를 자체적으로 하지

않고, 필요할 경우 동기화 메서드를 이용해서 동기화 처리가 가능하도록 변경하였다.

 

** 배열을 이용한 자료 구조 : 데이터를 읽어오고 저장하는데는 효율성이 좋지만 용량을 변경해야

할때는 새로운 배열을 생성한 후 기존의 데이터를 새로운 배열로 복사해야 하기 때문에 효율이

떨어짐.

 

** ArrayList 는 기존의 Vector 를 개선한 것으로 Vector 와 구현원리와 기능적인 측명이 동일하다.

Vector 는 기존에 작성된 소스와의 호환성을 위해 계속 남겨두고 있을 뿐이므로 가능하면

ArrayList 를 사용하자.

 

 

** 메소드 (Vector 기준)

구분

메소드

설명

생성자

Vector()

디폴트생성자

Vector(int capa)

주어진 capa만큼의 저장 공간을 가직 백터 생성

Vector(int capa, int capaincre)

주어진 capa 의 저장 공간을 정해주고 저장 공간이 다

차게 되면 capaincrement 만큼 저장공간을 늘려준다.

저장

boolean add(E o)

객체를 저장함. 맨뒤에 붙이기

boolean add(int index, E element)

index 로 지정된 위치에 객체 저장 (밀어내기)

E set(int index, E element)

index 로 지정된 위치에 객체 교환 (덮어쓰기)

접근

E get(int index)

index 로 지정된 요소 반환

E firstElement()

Vector 의 첫 번째 요소를 반환

E lastElement()

Vector 의 마지막 요소를 반환

삭제

E remove(int index)

index 로 주어진 위치에 존재하는 객체 지우고 지워진 객체반환

boolean remove(O o)

주어진 객체와 같은 객체를 지우기. 단, 첫 번째 객체의

레퍼런스만 지워짐 (이동일어남. 자리채우기)

void clear()

Vector 에 저장된 모든 객체 지우기

찾기

boolean contains(O elem)

특정객체의 백터포함 여부

int indexOf(O elem)

해당 객체의 위치 반환

int lastIndexOf(O elem)

해당 객체의 마지막 위치를 반환

int size()

벡터안의 객체 수를 반환

boolean isEmpty()

벡터가 비어있는지 확인. 비어 있으면 true

 

 

 

2.8 LinkedList 클래스

 

** 배열 : 가장 기본적인 형태의 자료구조로 구조가 간단하여 사용하지 쉽고 데이터를 읽어오는데 걸리는

시간(접근시간, access time)이 가장 빠르다.

- 단점 1) 크기를 변경할 수 없다

2) 비순차적인 데이터의 추가 또는 삭제에 시간이 많이 걸림.

 

---> LinkedList 는 이러한 단점을 보완하기 위해 고안됨. LinkedList 는 불연속적으로 존재하는 데이터를

서로 연결한 형태. LinkedList 의 각 요소들은 자신과 연결된 다음 요소에 대한 참조(주소값)와

데이터로 구성되어 있다.

 

** LinkedList 의 데이터 삭제

: 삭제하고자 하는 요소의 이전 요소가 삭제하고자 하는 요소의 다음 요소를 참조하도록 변경하기만

하면 됨. 처리 속도가 빠름

 

** LinkedList 의 데이터 추가

: 새로운 요소를 생성한 다음 추가하고자 하는 위치의 이전 요소의 참조를 새로운 요소에 대한 참조로

변경해 주고 새로운 요소가 그 다음 요소를 참조하도록 변경하기만 하면 됨. 처리속도가 빠름.

 

** LinkedList 는 이동방향이 단방향이기 때문에 다음 요소에 대한 접근은 쉽지만 이전요소에 대한 접근

은 어렵다. 이점을 보완한 것이 <더블링크드리스트(doublelinkedlist)> 이다. 링크드리스트보다 더

많이 사용됨.

 

2.9 ArrayList 와 LinkedList 의 비교

 

** 데이터의 추가 / 삭제 비교

import java.util.*;

 

public class ArrayListLinkedListTest {

public static void main(String args[]) {

// 추가할 데이터의 개수를 고려하여 충분히 잡아야한다.

ArrayList al = new ArrayList(1000000);

LinkedList ll = new LinkedList();

 

System.out.println("= 순차적으로 추가하기 =");

System.out.println("ArrayList :"+add1(al));

System.out.println("LinkedList :"+add1(ll));

 

System.out.println();

System.out.println("= 중간에 추가하기 =");

System.out.println("ArrayList :"+add2(al));

System.out.println("LinkedList :"+add2(ll));

 

System.out.println();

System.out.println("= 중간에서 삭제하기 =");

System.out.println("ArrayList :"+remove2(al));

System.out.println("LinkedList :"+remove2(ll));

 

System.out.println();

System.out.println("= 순차적으로 삭제하기 =");

System.out.println("ArrayList :"+remove1(al));

System.out.println("LinkedList :"+remove1(ll));

}

 

public static long add1(List list) {

long start = System.currentTimeMillis();

for(int i=0; i<100000;i++) list.add(i+"");

long end = System.currentTimeMillis();

return end - start;

}

 

public static long add2(List list) {

long start = System.currentTimeMillis();

for(int i=0; i<1000;i++) list.add(500, "X");

long end = System.currentTimeMillis();

return end - start;

}

 

public static long remove1(List list) {

long start = System.currentTimeMillis();

for(int i=list.size()-1; i > 0;i--) list.remove(i);

long end = System.currentTimeMillis();

return end - start;

}

 

public static long remove2(List list) {

long start = System.currentTimeMillis();

for(int i=0; i<1000;i++) list.remove(i);

long end = System.currentTimeMillis();

return end - start;

}

}

 

** 결과

= 순차적으로 추가하기 =

ArrayList : 591

LinkedList : 721

 

= 중간에 추가하기 =

ArrayList : 3465

LinkedList : 10

 

= 중간에 삭제하기 =

ArrayList : 3415

LinkedList : 10

 

= 순차적으로 삭제하기 =

ArrayList : 10

LinkedList : 50

 

<결론1> 순차적으로 추가/삭제하는 경우에는 ArrayList 가 LinkedList 보다 빠르다.

<결론2> 중간에 데이터를 추가/삭제하는 경우에는 LinkedList 가 ArrayList 보다 빠르다.

 

** 데이터의 접근

import java.util.*;

 

public class ArrayListLinkedListTest2 {

public static void main(String args[]) {

ArrayList al = new ArrayList(1000000);

LinkedList ll = new LinkedList();

add(al);

add(ll);

 

System.out.println("= 접근시간테스트 =");

System.out.println("ArrayList :"+access(al));

System.out.println("LinkedList :"+access(ll));

}

 

public static void add(List list) {

for(int i=0; i<100000;i++) list.add(i+"");

}

 

public static long access(List list) {

long start = System.currentTimeMillis();

for(int i=0; i<10000;i++) list.get(i);

long end = System.currentTimeMillis();

return end - start;

}

}

 

** 결과

= 접근시간테스트 =

ArrayList : 10

LinkedList : 3195

 

--> 배열은 각 요소들이 연속적으로 메모리상에 존재하기 때문에 간단한 계산만으로 원하는 데이터의

주소를 얻어서 저장된 데이터를 곧바로 읽어올 수가 있지만, LinkedList 는 각 요소들이 불연속적으로

연결되어 있어서 처음부터 n번째 데이터까지 차례대로 따라가야만 원하는 값을 얻을 수 있다.

그래서, LinkedList 는 저장해야하는 데이터의 개수가 많아질 수록 데이터를 읽어 오는 시간, 즉

접근시간(access time)이 길어진다는 단점이 있다.

 

컬렉션

읽기(접근시간)

추가 / 삭제

비 고

ArrayList

빠르다

느리다

순차적인 추가삭제는 빠름

비효율적인 메모리 사용

LinkedList

느리다

빠르다

데이터가 많을 수록 접근성이 떨어짐

 

<결론> 다루고자 하는 데이터의 개수가 변하지 않는 경우라면, ArrayList 가 최상의 선택이 되겠지만,

데이터의 개수가 변경이 잦다면 LinkedList 를 사용하는 것이 더 나은 선택이 될 것이다.

 

**두 클래스의 장점을 이용해서 두 클래스를 혼합해서 사용하는 방법도 있다. 처음 작업하기 전에

데이터를 저장할 때는 ArrayList 를 사용한 다음 작업할 때는 LinkedList 로 데이터를 옮겨서 작업

하면 좋은 효율을 얻을 수 있다.

 

 

2.10 Stack 과 Queue

 

** Stack 클래스 : 요소를 데이터 구조의 한쪽 단에서만 저장/접근할 수 있는 컬렉션

LIFO (last in first out)

구분

Stack 클래스

Queue 인터페이스

구조

LIFO

FIFO

생성

new 연산자로 생성

Stack s = new Stack();

queue인터페이스를 구현한 클래스로 생성

Queue q = new LinkedList();

메소드

E push() : 맨 위에 객체 추가

boolean offer(E o) : 큐에 객체 넣기

E pop() :

맨위 객체를 반환. 맨위 객체 제거됨(꺼내기)

E poll() : 큐에서 데이터 꺼내기

(비어있으면 null. 자리이동 일어남)

E peek() : 맨 위 객체 반환

(객체 제거 안됨)

E peek() : 맨 아래 객체 반환

(객체 제거 안됨)

boolean empty() : 스택이 비었는지 확인

 

활용 예

수식 계산, 수식 괄호 검사, 워드의 undo/redo, 웹브라우저의 뒤로/앞으로

최근 사용문서, 인쇄 작업 대기목록, 버퍼


댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2024/05   »
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 28 29 30 31
글 보관함