Home 컬렉션 프레임워크(List, Set, Map)
Post
Cancel

컬렉션 프레임워크(List, Set, Map)

컬렉션 프레임워크

컬렉션데이터 그룹을 크게 3가지 타입이 존재한다고 인식하고 각 컬렉션을 다루는데 필요한 기능을 가진 3개의 인터페이스를 정의했다. 그리고 인터페이스 List와 Set의 공통된 부분을 다시 뽑아 새로운 인터페이스인 Collection을 추가로 정의했다.

Map은 List와 Set처럼 공통부분이 많지않아 같은 상속계층도에 포함되지 못했다.

  • List : 순서가 있는 데이터의 집합. 데이터의 중복을 허용한다.
    • ArrayList, LinkedList, Stack, Vector 등
  • Set : 순서를 유지하지 않는 데이터의 집합. 데이터의 중복을 허용하지 않는다. ex) 양의 정수 집합, 소수의 집합 등
    • HashSet, TreeSet 등
  • Map : Key와 Value의 쌍으로 이루어진 데이터의 집합. 순서는 유지되지 않으며, 키는 중복을 허용하지 않고 값은 중복을 허용한다.
    • HashMap, TreeMap, Hashtable, Properties 등

컬렉션 프레임워크의 모든 컬렉션 클래스들은 List, Set, Map 셋 중 하나를 구현하고 있다. 대부분은 HashMap과 같이 이름에 포함되어 있지만 Vector, Stack, Hashtable, Properties와 같은 클래스들은 컬렉션프레임워크가 만들어지기 전부터 존재하던 것이라 예외이다.

** Vector -> ArrayList Hashtable -> HashMap 을 사용하는 것이 좋다.

Collection interface (List, Set 사용가능)

메서드설명
boolean add(Object o)지정된 객체 또는 Collection의 객체들을 Collection에 추가.
void clear()Collection의 모든 객체 삭제
boolean contains(Object o)지정된 객체 또는 Collection의 객체들이 Collection에 포함되어 있는지.
boolean equals(Object o)동일한 collection인지
int hashCode()Collection의 hashCode를 반환
boolean isEmpty()비어있는지
Iterator iterator()Iterator 반환
boolean remove(Object o)지정 객체 삭제
boolean removeAll(Collection c)지정된 Collection의 모든 객체 삭제
boolean retainAll(Collection c)지정된 Collection에 포함된 객체만을 남기고 다른 객체들은 Collection 에서 삭제한다. 이 작업으로 인해 Colleciton에 변화가 있으면 true, 없으면 false반환.
int size()저장된 객체의 개수 반환
Object[] toArray()Collection에 저장된 객체를 객체배열로 반환
Object[] toArray(Object[] a)지정된 배열에 Collection 객체를 저장해서 반환

List interface

메서드설명
void add(int index, Object element)지정된 위치에 객체 또는 컬렉션에 포함된 객체들을 추가
Object get(int index)지정된 위치에 있는 객체 반환
int IndexOf(Object o)지정된 객체의 위치를 반환 (List의 첫번째 요소부터 순방향으로 찾는다.)
int lastIndexOf(Object o)지정된 객체의 위치를 반환 (List의 마지막 요소부터 역방향으로 찾는다.)
ListIterator listIterator()List의 객체에 접근할 수 있는 ListIterator 반환
Object remove(int index)지정된 위치에 있는 객체를 삭제하고 객체 반환
Object set(int index, Object element)지정된 위치에 객체를 저장
void sort(Comparator c)지정된 비교자로 List를 정렬
List subList(int fromIndex, int toIndex)지정된 범위에 있는 객체를 반환

Map interface

메서드설명
void clear()Map의 모든 객체 삭제
boolean containsKey(Object key)지정된 key객체와 일치하는 Map의 key객체가 있는지 확인
boolean containsValue(Object value)지정된 value객체와 일치하는 Map의 value객체가 있는지 확인
Set entrySet()Map에 저장되어 있는 key-value 쌍을 Map.Entry타입의 객체로 저장한 Set으로 반환
boolean equals(Object o)같은지 확인
Object get(Object key)지정된 key객체에 대응하는 value객체를 찾아서 반환
int hashCode()해시코드 반환
boolean isEmpty()비었는지 확인
Set keySet()Map에 저장된 모든 key객체 반환
Object put(Object key, Object value)Map에 value객체를 key객체에 연결하여 저장
void putAll(Map t)지정된 Map의 모든 key-value쌍을 추가
Object remove(Object key)지정한 key객체와 일치하는 key-value 삭제
int size()key-value쌍의 개수 반환
Collection values()Map에 저장된 모든 value객체 반환

** value는 중복을 허용하기 때문에 Collection타입으로 반환하고 key는 중복을 허용하지 않기 때문에 Set 타입으로 반환한다.

ArrayList (List)

List 인터페이스를 구현하기 때문에 데이터의 저장순서가 유지되고 중복을 허용한다.

메서드설명
Object clone()복제
void ensureCapacity(int minCapacity)Array의 용량이 최소 minCapacity가 되도록 한다.
void trimToSize()용량을 크기에 맞게 줄인다. (빈 공간 없애기)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
final int LIMIT = 10;
String source = "0123456789abcdefghijklmnopqrstuvwxyz";
int length = source.length();

List list = new ArrayList(length/LIMIT + 10);

for(int i = 0; i < length; i+=LIMIT){
	if(i+LIMIT < length)
		list.add(source.substring(i, i+LIMIT);
	else
		list.add(source.substring(i);
}

for(int i = 0; i < list.size(); i++)
	System.out.println(list.get(i));

LinkedList (List)

Array는 구조가 간단하고 사용하기 쉽고 데이터를 읽어오는데 걸리는 시간이 가장 빠르다는 장점이 있지만 다음과 같은 단점이 있다.

  1. 크기를 변경할 수 없다.
  2. 비순차적인 데이터의 추가 또는 삭제에 시간이 많이 걸린다.

이러한 단점을 보완한 것이 LinkedList이다. LinkedList는 double LinkedList로 구현되어 있다.

1
2
3
4
5
class Node{
	Node next;
	Node previous;
	Object obj;
}
메서드설명
Object element()LinkedList의 첫번째 요소를 반환
Object peek()LinkedList의 첫번째 요소를 반환
Object poll()LinkedList의 첫번째 요소를 반환하고 LinkedList에서 제거
Object remove()LinkedList의 첫번째 요소를 제거
void addFirst(Object o)맨 앞에 객체 추가
void addLast(Object o)맨 끝에 객체 추가
Iterator descendingIterator()역순 조회를 위한 Iterator 반환
void push(Object o)addFirst(Object o)와 동일

** 순차적으로 추가/삭제하는 경우 ArrayList가 더 빠르다. ** 중간 데이터를 추가/삭제하는 경우 LinkedList가 더 빠르다.

컬렉션읽기(접근시간)추가/삭제비고
ArrayList빠름느림순차적인 추가 삭제는 더 빠름. 비효율적인 메모리 사용
LinkedList느림빠름데이터가 많을수록 접근성이 떨어짐

Stack & Queue

**stack(LIFO) - 수식계산, 웹브라우저의 뒤로/앞으로

메서드설명
Object peek()Stack의 맨 위에 저장된 객체를 반환. pop()처럼 꺼내지는 않음
Object pop()Stack의 맨 위에 저장된 객체를 꺼냄
Object push()Stack에 객체 저장
int search(Object o)Stack에서 주어진 객체를 찾아 그 위치를 반환

**Queue(FIFO) - 최근사용문서, 인쇄작업 대기목록 | 메서드 | 설명 | |–|–| | boolean add(Obejct o) | 지정된 객체를 Queue에 추가. 성공하면 true반환. | |Object remove()|Queue에서 객체를 꺼내 반환| |Object element()|삭제없이 요소를 읽어옴. peek와 다른점은 Queue가 비었을 때 Exception 발생| |boolean offer(Object o)|Queue에 객체를 저장| |Object poll()|Queue에서 객체를 꺼내 반환| |Object peek()|삭제없이 요소를 읽어옴|

  • PriorityQueue 저장한 순서에 관계없이 우선순위가 높은 것부터 꺼낸다. 각 요소를 heap으로 저장.
1
2
3
4
5
6
7
Queue pq = new PriorityQueue();
pq.offer(2);
pq.offer(3);
pq.offer(1);

while((obj = pq.poll()) != null)
	System.out.println(obj); // 1 2 3 출력.
  • Deque Queue의 변형으로 양방향으로 추가/삭제 가능.

offerLast() = offer(), push() pollLast() = pop() pollFirst() = poll() peekFirst() = peek() - Queue peekLast() = peek() - Stack

Iterator, ListIterator, Enumeration

모두 컬렉션에 저장된 요소를 접근하는데 사용되는 인터페이스. Enumeration은 Iterator의 구 버전이고 ListIterator는 Iterator를 향상시킨 것.

메서드설명
boolean hasNext()읽어올 요소가 남아있는지 체크
Object next()다음 요소를 읽어온다.
void remove()next()로 읽어온 요소를 삭제한다.
1
2
3
4
5
Collection c = new ArrayList();
Iterator it = c.iterator();

while(it.hasNext())
	System.out.println(it.next());

** Map인터페이스를 구현한 컬렉션 클래스는 키와 값을 쌍으로 저장하고 있어 iterator를 직접 호출할 수 없고, 그 대신 keySet()이나 entrySet()과 같은 메서드를 통해 키와 값을 각각 따로 Set의 형태로 얻어 온 후 다시 iterator를 호출해야 Iterator를 얻을 수 있다.

1
2
Map map = new HashMap();
Iterator it = map.entrySet().iterator(); //set인스턴스의 iterator()를 호출한 것과 같다.

** List 클래스들은 저장순서를 유지하기 때문에 Iterator를 이용해 읽어온 결과 역시 저장순서와 동일하지만 Set클래스들은 그렇지 않기 때문에 Iterator를 이용해 읽어와도 처음 저장한 순서와 같지 않다.

Iterator는 단방향으로만 이동할 수 있는데 ListIterator는 양방향으로의 이동이 가능하다. 다만 ArrayList나 LinkedList와 같이 List 인터페이스를 구현한 컬렉션에서만 이용가능하다.

1
2
3
4
5
6
7
8
ListIterator it = list.listIterator();

while(it.hasNext())
	System.out.println(it.next());
	it.remove() // 읽어오면서 삭제. 꼭 next와 함께 사용해야 한다.

while(it.hasPrevious())
	System.out.println(it.previous());

Arrays

  • 배열의 복사: copyOf(), copyOfRange()
  • 배열 채우기: fill(), setAll()
  • 배열의 정렬과 검색: sort(), binarySearch()
  • 배열의 비교와 출력: equals(), toString(), deepToString()
  • 배열을 List로 변환: asList()
1
2
3
Arrays.binarySearch(arr,2); //정렬상태에서만 사용가능.
Arrays.toString(arr); // [0,1,2,3,4]
Arrays.deepToString(arr); // [[11,12], [13,14]]

Comparator, Comparable

둘 모두 컬렉션을 정렬하는데 필요한 메서드를 정의하고 있으며 Arrays.sort()같은 경우에도 구현부에 이용된다.

HashSet

Set 인터페이스를 구현한 대표적인 컬렉션. 중복된 요소를 저장하지 않는다. 저장순서를 유지하지 않으므로 저장순서를 유지하고 싶다면 LinkedHashSet을 사용해야 한다.

1
2
3
4
5
Object[] objArr = {"1", new Integer(1), "2", "2", "2", "3", "3"}
Set set = new HashSet();
for(int i = 0; i < objArr.length; i++)
	set.add(objArr[i]);
// 1,1,2,3,4를 출력하게 된다.

** 중복값이 출력되지 않으며 1이 두번 있는 것은 하나는 String 하나는 Integer이기 때문.

1
2
3
4
5
6
7
8
9
10
11
12
13
Set set = new LinkedHashSet();
int[][] board = new int[5][5];

for(int i = 0; set.size() < 25; i++)
	set.add((int) (Math.random()*50)+1+"");

Iterator it = set.iterator();

for(int i = 0; i < board.length; i++)
	for(int j = 0; j < board[i].length; j++)
		board[i][j] = Integer.parseInt((String)it.next());

// 1~50 사이의 숫자중 25개를 골라 5*5 빙고판 만드는 예제. 중복값이 없다. 로또번호 등에 이용가능.

TreeSet

이진검색트리 자료구조 형태로 데이터를 저장하는 컬렉션 클래스. 정렬, 검색, 범위검색에 높은 성능을 보인다.

중복된 데이터 허용하지 않으며 정렬된 위치에 저장하므로 저장순서를 유지하지도 않는다.

메서드설명
NavigableSet descendingSet()TreeSet에 저장된 요소들을 역순으로 정렬해 반환
Object first()정렬된 순서에서 첫 번째 객체를 반환
Object floor(Object o)지정된 객체와 같은 객체를 반환. 없으면 작은값을 가진 객체중 제일 가까운 값의 객체를 반환
SortedSet headSet(Object toElement)지정된 객체보다 작은 값의 객체들을 반환
NavigableSet headSet(Object toElement, boolean inclusive)지정된 객체보다 작은 값의 객체들을 반환 (inclusive가 true이면 같은 값의 객체도 포함)
Object higher(Object o)지정된 객체보다 큰 값의 객체 중 가장 가까운 객체 반환
Object pollFirst()TreeSet의 첫번째요소(제일 작은 값) 반환
Object pollLast()TreeSet의 마지막요소(제일 큰 값) 반환
SortedSet subSet(Object fromElement, Object toElemet)범위검색의 결과를 반환한다. 끝범위인 toElement 미포함
SortedSet tailSet(Object fromElement)지정된 객체보다 큰 값의 객체들을 반환
1
2
3
4
5
6
7
8
9
10
11
12
13
TreeSet set = new TreeSet();

String from = "b";
String to = "d";

set.add("abc"); set.add("alien"); set.add("bat");
set.add("car"); set.add("disc"); set.add("dZZZZ");
set.add("elevator");

System.out.println(set.subSet(from, to));
// bat, car 출력
System.out.println(set.subSet(from, to + "zzz"));
// bat, car, disc, dZZZZ 출력 (끝범위인 d까지 포함시키려면 zzz와 같은 문자열을 붙이면 된다.)
1
2
3
4
5
6
7
8
TreeSet set = new TreeSet();
int[] score = {80, 95, 50, 35, 45};

for(int i = 0; i < score.length; i++)
	set.add(new Integer(score[i]));

System.out.println(set.headSet(new Integer(50)); // 50보다 작은 값 출력
System.out.println(set.tailSet(new Integer(50)); // 50보다 큰 값 출력

HashMap, Hashtable

Hashtable의 최신 버전이 HashMap이다.

해싱을 사용하기 때문에 많은 양의 데이터를 검색하는데 뛰어난 성능을 보인다.

1
2
3
4
HashMap map = new HashMap();
map.put("myId", "1234");
map.put("data", "1234"); // 저장 X, 값이 1111로 덮어씌워짐.
map.put("data", "1111"); 

** 해싱 - 해시함수를 이용해 데이터를 해시테이블에 저장하고 검색하는 기법을 의미한다. 데이터가 저장되어 있는 곳을 알려주기 때문에 다량의 데이터 중에서도 원하는 데이터를 빠르게 찾을 수 있다.

TreeMap

이진트리 형태로 저장한 Map 검색에 관한 대부분의 경우 HashMap이 더 뛰어난 성능을 보이지만 범위검색이나 정렬이 필요한 경우에는 TreeMap을 이용하는 것이 좋다.

subMap(), tailMap() 등의 메서드가 있다.

** 메서드는 필요 시 검색

Properties

HashMap의 구버전인 Hashtable을 상속받아 구현한 것으로 Hashtable은 키와 값을 (Object, Object) 형태로 저장하는데 비해 Properties는 (String, String) 형태로 저장한다.

주로 애플리케이션의 환경설정과 관련된 속성을 저장하는데 사용된다.

** 메서드는 필요 시 검색

Collections

컬렉션과 관련된 메서드들을 제공한다.

  • 컬렉션의 동기화
  • 멀티쓰레드 프로그래밍에서는 하나의 객체를 여러 쓰레드가 동시에 접근할 수 있기 때문에 데이터의 일관성을 유지하기 위해서는 공유되는 객체에 동기화가 필요하다.

static Collection synchronizedCollection(Collection c) static List synchronizedList(List list)

  • 변경불가 컬렉션 만들기

컬렉션에 저장된 데이터를 보호하기 위해 변경할 수 없도록 즉 읽기 전용으로 만들 때 사용한다.

static Collection unmodifiableCollection(Collection c)

  • 싱글톤 컬렉션 만들기

static List singletonList(Object o)

  • 한 종류의 객체만 저장하는 컬렉션 만들기

static List checkedList(List list, Class type)

1
2
List list = new ArrayList();
List checkedList = checkedList(list, String.class);

요약

컬렉션특징
ArrayList배열기반, 데이터의 추가와 삭제에 불리, 순차적인 추가삭제는 제일 빠름. 임의의 요소에 대한 접근성이 뛰어남
LinkedList연결기반, 데이터의 추가와 삭제에 유리. 임의의 요소에 대한 접근성이 좋지 않음
HashMap배열과 연결이 결합된 형태. 추가,삭제,검색,접근성이 모두 뛰어남. 검색에는 최고 성능을 보인다.
TreeMap연결기반. 정렬과 검색, 특히 범위검색에 적합. 검색성능은 HashMap보다 떨어짐
StackVector을 상속받아 구현
QueueLinkedList가 Queue 인터페이스를 구현
PropertiesHashtable을 상속받아 구현
HashSetHashMap을 이용해 구현
TreeSetTreeMap을 이용해 구현
LinkedHashMap, LinkedHashSetHashMap, HashSet에 저장순서유지기능을 추가.
This post is licensed under CC BY 4.0 by the author.