컬렉션 프레임워크(Collection Framework)

Nak Jun Choi·2022년 11월 10일

컬렉션 프레임 워크란?

컬렉션 프레임워크

  • 컬렉션이란 여러 데이터들의 집합을 의미한다.
  • 컬렉션을 다루는 데에 있어 편리한 메서드들을 미리 정의해놓은 것을 컬렉션 프레임 워크라고 한다.
  • 특정 자료구조에 데이터를 추가하고, 삭제하고, 수정하고, 검색하는 등의 동작을 수행하는 편리한 메서드들을 제공한다.

컬렉션 프레임워크의 구조

  • 컬렉션 프레임워크는 주요 인터페이스로 List, Set, Map을 제공한다.

  • List

    • List는 데이터의 순서가 유지되며, 중복 저장이 가능한 컬렉션을 구현한다.
    • ArrayList, Vector, Stack, LinkedList 등이 List 인터페이스를 구현한다.
  • Set

    • Set은 데이터의 순서가 유지되지 않으며, 중복 저장이 불가능한 컬렉션을 구현하는 데에 사용된다.
    • HashSet, TreeSet 등이 Set 인터페이스를 구현한다.
  • Map

    • Map은 키(key)와 값(value)의 쌍으로 데이터를 저장하는 컬렉션을 구현하는 데에 사용된다.
    • 데이터의 순서가 유지되지 않으며, 키는 값을 식별하기 위해 사용되므로 중복 저장이 불가능하지만, 값은 중복 저장이 가능하다.
    • HashMap,HashTable, TreeMap, Properties 등이 Map 인터페이스를 구현한다.
    • List와 Set은 서로 공통점이 많아 위 그림과 같이 Collecntion이라는 인터페이스로 묶인다. 이 둘의 공통점이 추출되어 추상화 된것이 Collection 인터페이스이다.

컬렉션 인터페이스

List<E>

List

  • 배열과 같이 객체를 일렬로 늘어놓은 구조를 가지고 있다.
  • 객체를 인덱스로 관리한다.
  • 인덱스로 객체를 검색, 추가, 삭제할 수 있다.

ArrayList

  • 기능적으로 Vector와 동일하지만 기존의 Vector를 개선한 것이므로, Vector보다는 주로 ArrayList를 사용한다.

  • 객체가 인덱스로 관리된다.

  • 저장용량이 초가되면 자동으로 늘어난다.

  • 데이터가 연속적으로 존재한다.

  • 특정 인덱스의 객체를 제거하면, 바로 뒤 인덱스부터 마지막 인덱스까지 모두 앞으로 1씩 당겨진다.

        // ArrayList를 생성하여 list에 할당
		ArrayList<String> list = new ArrayList<String>();

		// String 타입의 데이터를 ArrayList에 추가
		list.add("Java");
		list.add("egg");
		list.add("tree");

		// 저장된 총 객체 수 얻기
		int size = list.size(); 

		// 0번 인덱스의 객체 얻기
		String skill = list.get(0);

		// 저장된 총 객체 수 만큼 조회
		for(int i = 0; i < list.size(); i++){
			String str = list.get(i);
			System.out.println(i + ":" + str);
		}

		// for-each문으로 순회 
		for (String str: list) {
			System.out.println(str);
		}		

		// 0번 인덱스 객체 삭제
		list.remove(0);
        

LinkedList

  • Linked 컬렉션은 데이터를 효율적으로 추가, 삭제, 변경하기 위해 사용된다.

  • 데이터들이 불연속적으로 존재한다.

  • 데이터끼리 서로 연결(Link)되어 있다.

  • 배열처럼 데이터를 이동하기 위해 복사할 필요가 없기 때문에 처리속도가 훨씬 빠르다.

        // Linked List를 생성하여 list에 할당
		ArrayList<String> list = new LinkedList<>();

		// String 타입의 데이터를 LinkedList에 추가
		list.add("Java");
		list.add("egg");
		list.add("tree");

		// 저장된 총 객체 수 얻기
		int size = list.size(); 

		// 0번 인덱스의 객체 얻기
		String skill = list.get(0);

		// 저장된 총 객체 수 만큼 조회
		for(int i = 0; i < list.size(); i++){
			String str = list.get(i);
			System.out.println(i + ":" + str);
		}

		// for-each문으로 순회
		for (String str: list) {
			System.out.println(str);
		}		

		// 0번 인덱스 객체 삭제
		list.remove(0);

ArrayList와 LinkedList의 차이

  • ArrayList에서 데이터를 추가 또는 삭제하려면 다른 데이터를 복사해서 이동해야한다.
    • 순차적으로 저장할 때는 데이터를 이동하지 않아도 되므로 작업 속도가 빠르다.
    • 중간에 위치한 객체를 추가 및 삭제할 때에는 데이터 이동이 많이 일어나므로 속도가 저하된다.
    • 검색(읽기) 측면에서는 유리하다.
  • LinkedList
    • 데이터를 중간에 추가하거나 삭제하는 경우, LinkedList는 ArrayList보다 빠른 속도를 보여준다.
    • 검색에 있어서는 ArrayList보다 상대적으로 느리다.
  • 데이터의 잦은 변경이 예상된다면 LinkedList를, 데이터의 개수가 변하지 않는다면 ArrayList를 사용하는 것이 좋다.

Iterator

Iterator

  • 반복자라는 의미를 가진다.
  • 컬렉션에 저장된 요소들을 순차적으로 읽어오는 역할을 한다.
  • Collection 인터페이스를 상속받은 List와 Set 인터페이스를 구현한 클래스들은 iterator() 메서드를 사용할 수 있다.
ArrayList<String> list = ...;
Iterator<String> iterator = list.iterator();

while(iterator.hasNext()) {     // 읽어올 다음 객체가 있다면 
	String str = iterator.next(); // next()를 통해 다음 객체를 읽어온다.
	...
}
ArrayList<String> list = ...;
for(String str : list) {
	...
}
ArrayList<String> list = ...;
Iterator<String> iterator = list.iterator();

while(iterator.hasNext()){        // 다음 객체가 있다면
	String str = iterator.next();   // 객체를 읽어오고,
	if(str.equals("str과 같은 단어")){ // 조건에 부합한다면
		iterator.remove();            // 해당 객체를 컬렉션에서 제거한다. 
	}
}

TreeSet

  • 이진 탐색 트리 형태로 데이터를 저장한다.
  • 데이터의 중복 저장을 허용하지 않고 저장 순서를 유지하지 않는 Set 인터페이스의 특징은 그대로 유지된다.
  • 하나의 부모 노드가 최대 두개의 자식 노드와 연결되는 이진 트리의 일종으로, 정렬과 검색에 특화된 자료 구조이다.
  • 최상의 노드를 '루트'라고 부른다
  • 모든 왼쪽 자식의 값이 루트나 부모보다 작고, 모든 오른쪽 자식의 값이 루트나 부모보다 큰 값을 가지는 특징이 있다.
  • String은 자동으로 사전 편찬 순에 따라 오름차순으로 정렬된다.(TreeSet의 기본 정렬 방식이 오름차순이다.)

Map<K,V>

  • 키(key)와 값(value)으로 구성된 객체를 저장하는 구조이다.
  • 객체를 Entry 객체라고 하는데, 이 Entry 객체는 키와 값을 각각 Key 객체와 Value 객체로 저장한다.
  • 키는 중복 저장될 수 없지마, 값은 중복 저장이 가능하다.
  • 만약 기존에 저장된 키와 동일한 키로 값을 저장하면, 기존의 값이 새로운 값으로 대처된다.

HashMap

  • HashMap은 Map 인터페이스를 구현한 대표적인 클래스이다. 키와 값으로 구성된 객체를 저장하는데, 이 객체를 Entry 객체라고 한다.
  • 삽입되는 순서와 위치 또한 관계가 없다.
  • 해싱(Hashing)을 사용하기 때문에 많은 양의 데이터를 검색하는 데 있어서 뛰어난 성능을 보인다.

  • Map 인터페이스의 내부 인터페이스인 Entry 인터페이스를 구현하며, Map.Entry 인터페이스에는 위와 같은 메서드가 정의되어져 있다.

  • HashMap 사용하는 방법

HashMap<String, Integer> hashmap = new HashMap<>();
import java.util.*;

public class HashMapExample {
    public static void main(String[] args) {

	    // HashMap 생성
        HashMap<String, Integer> map = new HashMap<>();

        // Entry 객체 저장
        map.put("피카츄", 85);
        map.put("꼬부기", 95);
        map.put("야도란", 75);
        map.put("파이리", 65);
        map.put("피존투", 15);

        // 저장된 총 Entry 수 얻기
        System.out.println("총 entry 수: " + map.size());

        // 객체 찾기
        System.out.println("파이리 : " + map.get("파이리"));
				
        // key를 요소로 가지는 Set을 생성 -> 아래에서 순회하기 위해 필요하다. 
        Set<String> keySet = map.keySet();

        // keySet을 순회하면서 value를 읽어온다. 
        Iterator<String> keyIterator = keySet.iterator();
        while(keyIterator.hasNext()) {
            String key = keyIterator.next();
            Integer value = map.get(key);
            System.out.println(key + " : " + value);
        }

        // 객체 삭제
        map.remove("피존투");

        System.out.println("총 entry 수: " + map.size());

        // Entry 객체를 요소로 가지는 Set을 생성 -> 아래에서 순회하기 위해 필요하다. 
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet();

        // entrySet을 순회하면서 value를 읽어온다. 
        Iterator<Map.Entry<String, Integer>> entryIterator = entrySet.iterator();
        while(entryIterator.hasNext()) {
            Map.Entry<String, Integer> entry = entryIterator.next();
            String key = entry.getKey(); // Map.Entry 인터페이스의 메서드
            Integer value = entry.getValue(); // Map.Entry 인터페이스의 메서드
            System.out.println(key + " : " + value);
        }

        // 객체 전체 삭제
        map.clear();
    }
}
  • Map은 키와 값을 쌍으로 저장하기 때문에 iterator()를 직접 호출할 수 없다. 그 대신 keySet()이나 entrySet() 메서드를 이용해 Set 형태로 반환된 컬렉션에 iterator()를 호출하여 반복자를 만든 후, 반복자를 통해 순회할 수 있다.

HashTable

  • HashTable은 HashMap과 내부 구조가 동일하며, 사용 방법 또한 매우 유사하다. 간단하게 HashMap이 HashTable의 새로운 버전이라고 이해하면 좋다.
import java.util.*;

public class HashTableExample {
    public static void main(String[] args){

        HashTable<String, String> map = new Hashtable<String, String>();

        map.put("Spring", "345");
        map.put("Summer", "678");
        map.put("Fall", "91011");
        map.put("Winter", "1212");

        System.out.println(map);

        Scanner scanner = new Scanner(System.in);

        while (true) {
            System.out.println("아이디와 비밀번호를 입력해 주세요");
            System.out.println("아이디");
            String id = scanner.nextLine();

            System.out.println("비밀번호");
            String password = scanner.nextLine();

            if (map.containsKey(id)) {
                if (map.get(id).equals(password)) {
                    System.out.println("로그인 되었습니다.");
                    break;
                } 
                else System.out.println("비밀번호가 일치하지 않습니다. ");
            } 
            else System.out.println("입력하신 아이디가 존재하지 않습니다.");
        }
    }
}
profile
HelloWorld

0개의 댓글