본문 바로가기
Back-end

11 컬렉션 프레임웍(1)

by 신재권 2021. 7. 6.

컬렉션 프레임웍

컬레션 프레임웍이란 데이터 군을 저장하는 클래스들을 표준화한 설계

컬렉션 프레임웍은 컬렉션, 다수의 데이터를 다루는데 필요하고 다양하고 풍부한 클래스들을 제공

컬렉션 프레임웍의 핵심 인터페이스

컬렉션 프레임웍에서는 컬렉션데이터 그룹을 크게 3가지 타입이 존재한다고 인식하고 각 컬렉션을 다루는데 필요한 기능을 가진 3가지 인터페이스를 정의함

인터페이스 List와 Set의 공통된 부분을 다시 뽑아서 새로운 인터페이스인 Collection을 추가로 정의

List : 순서가 있는 데이터의 집합, 데이터의 중복을 허용한다. ex) 대기자 명단

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

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

클래스 : HashSet, TreeSet 등

Map : 키(key)와 값(value)의 쌍(pair)으로 이루어진 데이터 집합, 순서는 유지되지 않고, 키는 중복을 허용하지 않고, 값은 중복을 허용한다. ex)우편번호 , 전화번호,

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

Collection 인터페이스

List와 Set의 조상인 Collection 인터페이스의 메서드들


boolean add(Object o) : 지정된 객체(o) 또는 Collection(c)의 객체들을 Collect에 추가한다.

boolean addAll(Collection c) :


void clear() : Collection의 모든 객체를 삭제한다.


boolean contains(Object o) : 지정된 객체(o) 또는 Collection의 객체들이 Collection에 포함

boolean containsAll(Collection c) : 되어 있는지 확인한다.


boolean equals(Object o) : 동일한 Collection인지 비교


int hashCode() : Collection의 hash code를 반환한다.


boolean isEmpty() : Collection이 비어있는지 확인한다.


Iterator iterator() : Collection의 Iterator를 얻어서 반환한다.


boolean remove(Obejct o) : 지정된 객체를 삭제한다.


boolean removeAll(Collection c) : 지정된 Collection에 포함된 객체들을 삭제한다.


boolean retainAll(Collection c) : 지정된 Collection에 포함된 객체만을 남기고 다른 객체들은 Collection에서 삭제한다. 이 작업으로 인해 Collection의 변화가 있으면 true, 없으면 false반환


int size() : Collection에 저장된 객체의 개수를 반환


Object[] toArray() : Collection에 저장된 객체를 객체배열(Object[])로 반환


Object[]toArray(Obejct[] a) : 지정된 배열에 Collection의 객체를 저장해서 반환


Collection 인터페이스는 컬렉션 클래스에 저장된 데이터를 읽고, 추가하고 삭제하는 등 컬렉션을 다루는데 가장 기본적인 메서드들을 정의

List인터페이스

List인터페이스는 중복을 허용하면서 저장순서가 유지되는 컬렉션을 구현하는데 사용됨

List인터페이스에 정의된 메서드는 다음과 같다. Collection인터페이스로부터 상속받은 메서드들은 제외


void add(int index, Object element) : 지정된 위치(index)에 객체(element)또는 컬렉션에 포함

boolean addAll(int index, Collection c) : 된 객체들을 추가한다.


Object get(int index) : 지정된 위치(index)에 있는 객체를 반환


int indexOf(Object o) : 지정된 객체의 위치(index)를 반환한다. (List의 첫번째 요소부터 찾음)


int lastindexOf(Object o) : 위와 동일, (List의 마지막 요소부터 찾음)


ListIterator listIterator() : List의 객체에 접근할 수 있는 ListIterator을 반환한다.

ListIterator listIterator(int index) :


Object remove(int index) :지정된 위치(index)에 있는 객체를 삭제하고, 삭제된 객체 반환


Object set(int index, Object element) : 지정된 위치(index)에 객체(element)를 저장한다.


void sort(Comparator c) : 지정된 비교자(comparator)로 List를 정렬한다.


List subList(int fromIndex, int toIndex) : 지정된 범위(fromIndex~toIndex)에 있는 객체를 반환


Set인터페이스

Set인터페이스는 중복을 허용하지 않고 저장순서가 유지되지 않는 컬렉션 클래스들을 구현하는데 사용된다. Set인터페이스르르 구현한 클래스로는 HashSet, TreeSet 등이 있다.

Map 인터페이스

Map인터페이스는 키와 값을 하나의 쌍으로 묶어서 저장하는 컬렉션 클래스를 구현하는데 사용된다. 키는 중복될 수 없지만 값은 중복을 허용한다.

기존에 저장된 데이터와 중복된 키와 값을 저장하면 기존의 값은 없어지고 마지막에 저장된 값이 남게된다.

Map인터페이스를 구현한 클래스는 Hashtable, HashMap, LinkedHashMap, SortedMap, TreeMap등이 있다.


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으로 반환한다.


Object get(Object key) : 지정한 key객체에 대응하는 value객체를 찾아서 반환한다.


int hashCode() : 해시코드를 반환한다.


boolean isEmpty() : Map이 비어있는지 확인한다.


Set keySet() : Map에 저장된 모든 key객체를 반환한다.


Object put(Object key, Object value) : Map에 value객체를 key객체에 연결(mapping)하여 저장한다.


void putAll(Map t) : 지정된 Map의 모든 key-value 쌍을 추가한다.


Object remove(Object key) : 지정한 key객체와 일치하는 key-value객체를 삭제한다.


int size() : Map에 저장된 key-value 쌍의 개수를 반환한다.


Collections values() : Map에 저장된 모든 value객체를 반환한다.


values()에서는 반환타입이 Collection이고, keySet()에서 반환타입이 Set인 것에 주ㅇ목하자. Map인터페이스에서 값은 중복을 허용하기 때문에 Collection타입으로 변환하고, 키는 중복을 허용하지 않기 때문에 Set타입으로 반환한다.

Map.Entry 인터페이스

Map.Entry 인터페이스는 Map인터페이스의 내부 인터페이스이다. 내부 클래와 같이 인터페이스도 인터페이스 안에 인터페이스를 정의하는 내부 인터페이스를 정의하는 것이 가능하다.

Map에 저장되는 key-value쌍을 다루기위해 내부적으로 Entry인터페이스를 정의했다.

public interface Map{
		...
		public static interface Entry {
			Object getKey();
			....
			}
	}

boolean equals(Object o) : 동일한 Entry인지 비교한다.


Object getKey() : Entry의 key객체를 반환한다.


Object getValue() : Entry의 value객체를 반환한다.


int hashCode() : Entry의 해시코드를 반환한다.


Object setValue(Object value) : Entry의 value객체를 지정된 객체로 바꾼다.


ArrayList

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

ArrayList는 Object배열을 이용해 데이터를 순차적으로 저장한다.

배열에 더이상 저장공간이 없으면 보다 큰 새로운 배열을 생성해서 기존의 배열에 저장된 내용을 새로운 배열로 복사한다음 저장

ArrayList 클래스 내부에는 Object배열을 멤버변수로 가지고 있어, 모든 종류의 객체를 담을수 있다.


Arraylist() : 크기가 10인 ArrayList를 생성


ArrayList(Collection c) : 주어진 컬렉션이 저장된 ArrayList를 생성


ArrayList(int initialCapacity) : 지정된 초기용량을 갖는 ArrayList를 생성


boolean add(Object o) : ArrayList의 마지막에 객체를 추가, 성공하면 true


void add(int index, Object element) : 지정된 위치(index)에 객체를 저장


boolean addAll(Collection c) : 주어진 컬렉션의 모든 객체를 저장한다.


boolean addAll(int index, Collection c) : 지정된 위치부터 주어진 컬렉션의 모든 객체를 저장


void clear() : ArrayList를 완전히 비운다.


Object clone() : ArrayLIst를 복제한다.


boolean contains(Object o) : 지정된 객체(o)가 ArrayList에 포함되어 있는지 확인


void ensureCapacity(int minCapacity) : ArrayList의 용량이 최소한 minCapacity가 되도록 한다.


Object get(int index) : 지정된 위치(index)에 저장된 객체를 반환한다.


int indexOf(Object o) : 지정된 객체가 저장된 위치를 찾아 반환한다.


boolean isEmpty() : ArrayList가 비어있는지 확인한다.


Iterator iterator() : ArrayLIst의 Iterator객체를 반환


int lastIndexOf(Object o) : 객체(o)가 지정된 위치를 끝부터 역방향으로 검색해서 반환


ListIterator listIterator() : ArrayList의 ListIterator을 반환


ListIterator listIterator(int index) : ArrayList의 지정된 위치부터 시작하는 ListIterator를 반환


Object remove(int index) : 지정된 위치(index)에 있는 객체를 제거


boolean remove(Object o) : 지정된 객체를 제거 (성공하면 true, 실패하면 false)


boolean removeAll(Collection c) : 지정한 컬렉션에 저장된 것과 동일한 객체들을 ArrayList에서 제거


boolean retainAll(Collection c) : ArrayList에 저장된 객체 중에서 주어진 컬렉션과 공통된 것들만을 남기고 나머지는 삭제


Object set(int index, Object element) : 주어진 객체(element)를 지정된 위치(index)에 저장한다.


int size() : ArrayLIst에 저장된 객체의 개수를 반환한다.


void sort(Comparator c) : 지정된 정렬기준으로 ArrayList를 정렬


List subList (int fromIndex, int toIndex) : fromIndex~toIndex사이에 저장된 객체를 반환


Object[] toArray() : ArrayList에 저장된 모든 객체들을 객체배열로 반환


Object[] toArray(Object[] a) : ArrayList에 저장된 모든 객체들을 객체배열 a에 담아 반환


void trimToSize() : 용량을 크기에 맞게 줄인다(빈공간을 없앤다)


import java.util.*;

public class ArrayListEx1 {

	public static void main(String[] args) {
		ArrayList list1 = new ArrayList(10);
		list1.add(new Integer(5));
		list1.add(new Integer(4));
		list1.add(new Integer(2));
		list1.add(new Integer(0));
		list1.add(new Integer(1));
		list1.add(new Integer(3));

		ArrayList list2 = new ArrayList(list1.subList(1, 4));
		print(list1, list2);

		Collections.sort(list1);
		Collections.sort(list2);
		print(list1, list2);

		// 포함되어 있는지 확인
		System.out.println("list1.containsAll(list2) : "
				+ list1.containsAll(list2));

		list2.add("B");
		list2.add("C");
		list2.add("A");
		print(list1, list2);

		list2.set(3, "AA");
		print(list1, list2);

		// list1에서 list2와 겹치는 부분만 남기고 나머지는 삭제한다.
		System.out.println("list1.retainAll(list2) : " + list1.retainAll(list2));
		print(list1, list2);

		// list2에서 list1에 포함된 객체들을 삭제한다.
		for (int i = list2.size() - 1; i >= 0; i--) {
			if (list1.contains(list2.get(i)))
				list2.remove(i);
		}
		print(list1, list2);

	}

	static void print(ArrayList list1, ArrayList list2) {
		System.out.println("list1:" + list1);
		System.out.println("list2:" + list2);
		System.out.println();
	}

}
---------------------
list1:[5, 4, 2, 0, 1, 3]
list2:[4, 2, 0]

list1:[0, 1, 2, 3, 4, 5]
list2:[0, 2, 4]

list1.containsAll(list2) : true
list1:[0, 1, 2, 3, 4, 5]
list2:[0, 2, 4, B, C, A]

list1:[0, 1, 2, 3, 4, 5]
list2:[0, 2, 4, AA, C, A]

list1.retainAll(list2) : true
list1:[0, 2, 4]
list2:[0, 2, 4, AA, C, A]

list1:[0, 2, 4]
list2:[AA, C, A]

위의 에제는 ArrayList의 기본적인 메서드를 이용해서 객체를 다룬다.

List인터페이스를 구현해씩 때문에 저장된 순서가 유지된다 .

import java.util.*;

public class ArrayListEx2 {

	public static void main(String[] args) {
		final int LIMIT = 10;
		String source = "0123456789abcdefghiABCDEFGHI!@#$%^&*()ZZZ";
		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));
		}

	}

}
----------------------
0123456789
abcdefghiA
BCDEFGHI!@
#$%^&*()ZZ
Z

ArrayList를 생성할 떄, 저장할 요소의 개수를 고려해서 실제 저장할 개수보다 약간 여유 있는 크기로 하는 것이 좋다. 생성할 떄 지정한 크기보다 더 많은 객체를 저장하면 자동적으로 크기가 늘어나기는 하지만, 이과정에서 처리시간이 많이 소요되기 떄문이다.

import java.util.*;

public class VectorEx1 {

	public static void main(String[] args) {
		Vector v = new Vector(5); // 용량(capacity)가 5인 Vector를 생성한다.
		v.add("1");
		v.add("2");
		v.add("3");
		print(v);

		v.trimToSize(); // 빈 공간을 없앤다. (용량과 크기가 같아진다)
		System.out.println("After trimToSize()");
		print(v);

		v.ensureCapacity(6);
		System.out.println("After ensureCapacity(6)");
		print(v);

		v.setSize(7);
		System.out.println("After setSize(7)");
		print(v);

		v.clear();
		System.out.println("After clear()");
		print(v);

	}

	public static void print(Vector v) {
		System.out.println(v);
		System.out.println("size : " + v.size());
		System.out.println("capacity : " + v.capacity());
	}

}
==================
[1, 2, 3]
size : 3
capacity : 5
After trimToSize()
[1, 2, 3]
size : 3
capacity : 3
After ensureCapacity(6)
[1, 2, 3]
size : 3
capacity : 6
After setSize(7)
[1, 2, 3, null, null, null, null]
size : 7
capacity : 12
After clear()
[]
size : 0
capacity : 12
  1. 다음 capcity가 5인 Vector인스턴스 v를 생성하고, 3개의 객체를 저장
  2. v.trimToSize()를 호출하면 v의 빈 공간을 없애서 size와 capacity가 같게한다. 배열은 크기 변경이 불가하기 때문에 새로운 배열을 생성해서 그 주소값을 변수 v에 할당한다.
  3. v.ensureCapcity(6)은 v의 capacity가 최소한 6이 되도록한다. v의 capacity가 6이상 이라면 아무일도 일어나지 않는다. 새로운 배열을 생성해서 v의 내용을 복사한다.
  4. v.setSize(7)은 v의 size가 7이되도록한다. 만일 v의 capacity가 충분하면 새로 인스턴스를 생성하지 않아도 되지만, 부족하면 현재 capacity의 크기보다 2배의 크기로 증가된다.
  5. v.clear()은 v의 모든 요소를 삭제한다.

ArrayList나 Vector 같이 배열을 이용한 자료구조는 데이터를 읽어오고 저장하는 데는 효율이 좋지만 , 용량을 변경할 때는 새로운 배열을 생성한 후 기존 배열의 데이터를 복사하기 때문에 효율이 떨어진다.

import java.util.*;

public class MyVector {
	Object[] data = null; // 객체를 담기 위한 객체배열 선언
	int capacity = 0; // 용량
	int size = 0; // 크기

	public MyVector(int capacity) {
		if (capacity < 0)
			throw new IllegalArgumentException("유효하지 않은 값입니다. : " + capacity);
		this.capacity = capacity;
		data = new Object[capacity];
	}

	public MyVector() {
		this(10); // 크기를 지정하지 않으면 크기를 10으로 한다.
	}

	// 최소한의 저장공간(capacity)를 확보하는 메서드
	public void ensureCapacity(int minCapacity) {
		if (minCapacity - data.length > 0)
			setCapacity(minCapacity);
	}

	public boolean add(Object obj) {
		// 새로운 객체를 저장하지 전에 저장할 공간을 확보한다.
		ensureCapacity(size + 1);
		data[size++] = obj;
		return true;
	}

	public Object get(int index) {
		if (index < 0 || index >= size)
			throw new IndexOutOfBoundsException("범위를 벗어났습니다.");
		return data[index];
	}

	public Object remove(int index) {
		Object oldObj = null;

		if (index < 0 || index >= size)
			throw new IndexOutOfBoundsException("범위를 벗어났습니다.");
		oldObj = data[index];

		// 삭제하고자 하는 객체가 마지막 객체가 아니라면, 배열복사를 통해 빈자리를 채워줘야 한다.
		if (index != size - 1) {
			System.arraycopy(data, index + 1, data, index, size - index - 1);
		}
		// 마지막 데이터를 null로 한다. 배열은 0부터 시작하므로 마지막 요소는 index가 size-1이다.
		data[size - 1] = null;
		size--;
		return oldObj;
	}

	public boolean remove(Object obj) {
		for (int i = 0; i < size; i++) {
			if (obj.equals(data[i])) {
				remove(i);
				return true;
			}
		}
		return false;
	}

	public void trimToSize() {
		setCapacity(size);
	}

	private void setCapacity(int capacity) {
		if (this.capacity == capacity)
			return; // 크기가 같으면 변경하지 않는다.

		Object[] tmp = new Object[capacity];
		System.arraycopy(data, 0, tmp, 0, size);
		data = tmp;
		this.capacity = capacity;
	}

	public void clear() {
		for (int i = 0; i < size; i++)
			data[i] = null;
		size = 0;
	}

	public Object[] toArray() {
		Object[] result = new Object[size];
		System.arraycopy(data, 0, result, 0, size);

		return result;
	}

	public boolean isEmpty() {
		return size == 0;
	}

	public int capacity() {
		return capacity;
	}

	public int size() {
		return size;
	}

	/* List인터페이스로부터 상속받은 메서드들 */
	// public int size();
	// public boolean isEmpty();
	public boolean contains(Object o) {
		for(int i=0; i<size; i++){
			if(data.equals(o))
				return true;
		}
		return false;
	}

	public Iterator iterator() {
		return null;
	};

	// public Object[] toArray();
	public Object[] toArray(Object a[]) {
		return null;
	}

	// public boolean add(Object o);
	public boolean addAll(Collection c) {
		return false;
	}

	public boolean addAll(int index, Collection c) {
		return false;
	}

	public boolean removeAll(Collection c) {
		return false;
	}

	public boolean retainAll(Collection c) {
		return false;
	}

	// public void clear();
	public boolean equals(Object o) {
		if(data == o) 
			return true;
		
		return false;
	}

	// public int hashCode();
	// public Object get(int index);
	public Object set(int index, Object element) {
		data[index] = element;

		return data;
	}

	public void add(int index, Object element) {
		ensureCapacity(size + 1);
		System.arraycopy(data, index, data, index+1, size-index );
		data[index] = element;
	}

	// public Object remove(int index);
	public int indexOf(Object o) {
		for(int i=0; i< size;i++){
			
		}
		return -1;
	}

	public int lastIndexOf(Object o) {
		return -1;
	}

	public ListIterator listIterator() {
		return null;
	}

	public ListIterator listIterator(int index) {
		return null;
	}

	public ListIterator subList(int fromIndex, int toIndex) {
		return null;
	}

	public static void main(String[] args) {

	}

}

위의 예제는 일부 메서드를 구현한 것이다.

'Back-end' 카테고리의 다른 글

11 컬렉션 프레임웍(2)  (0) 2021.07.06
03 SELECT문의 기본 형식  (0) 2021.07.06
02 관계형 데이터베이스와 오라클 데이터 베이스  (0) 2021.07.05
객체 지향 정리  (0) 2021.07.05
10 날짜와 시간 & 형식화 (4)  (0) 2021.07.05