Java

Java 컬렉션

김한토 2024. 8. 26. 12:51
반응형

자바 컬렉션(Java Collections)

: 자바에서 데이터를 효과적으로 저장하고 관리할 수 있도록 도와주는 프레임워크이다. 켈렉션을 여러 개의 객체를 모아 놓은 데이터 구조를 의미하고, 자바 컬렉션 프레임워크는 이러한 컬렉현을 쉽게 사용할 수 있는 여러 클래스와 인터페이스를 제공한다.

 

1. 컬렉션 프레임워크의 구성 요소

- Collection 인터페이스 : 모든 컬렉션의 최상위 인터페이스[1]*로, 리스트, 셋, 큐 등 여러 하위 인터페이스를 포함한다. 리스트(List), 셋(Set), 큐(Queue) 등 여러 하위 인터페이스를 포함한다. 

- Map 인터페이스 : 키-값 쌍으로 데이터를 저장하는 구조호, Collection과는 다르다. 키는 중복될 수 없고, 각 키에 대해 하나의 값만 연결한다. 

 

2. 주요 인터페이스 및 클래스

- Collection 인터페이스의 하위 인터페이스

1) List : 순서가 있는 데이터의 집합으로, 중복된 요소를 허용한다. 

1-1) ArrayList : 배열 기반의 리스트로, 인덱스를 통해 빠르게 접근할 수 있다. 하지만 요소를 추가하거나 제거할 때, 성능이 떨어질 수 있따. 

 

+-----+-----+-----+-----+-----+
|  0  |  1  |  2  |  3  |  4  |
+-----+-----+-----+-----+-----+
|  A  |  B  |  C  |  D  |  E  |
+-----+-----+-----+-----+-----+

크기가 가변적이며, 필요에 따라 자동으로 배열의 크기를 조정한다. 요소를 추가하거나 삭제할 때 성능이 좋다. (단, 중간에 요소를 삽입하거나 삭제할 경우 성능이 저하될 수 있다.) 배열 기반이라 인덱스를 통한 접근이 빠르다. 

import java.util.ArrayList;

public class Sample {
    public static void main(String[] args) {
        ArrayList foods = new ArrayList();
        foods.add("떡볶이");
        foods.add("마라탕");
        foods.add("케이크");
    }
}

ArrayList의 객체인 foos에 add 메서드를 이용하여 음식을 저장했다. 만약 첫 번째 위치에 돈까스를 추가하고 싶으면

foods.add(0,"돈까스")

다음과 같이 삽입할 위치를 파라미터로 넘겨줘야한다.  

을 사용하면 원하는 인덱스 값을 추출할 수 있따. 

 

get() : 해당 인덱스의 값을 추출한다. 

size() : arrayList의 요소의 개수를 리턴한다. 

contains() : 리스트 안에 해당 항목이 있는지 판별해 그 결과를 boolean으로 리턴한다. 

remove(객체) : 리스트에서 객체에 해당하는 항목을 삭제한 뒤, 그 결과로 true 또는 false를 리턴한다. 

remove(인덱스) : 리스트에서 해당하는 인덱스에 항목을 삭제한 뒤, 그 항목을 리턴한다.  

sort(Comparator.naturalOrder()) : 오름차순 정렬

sort(리스트, Comparator .reverseOrder()) : 내림차순 정렬 

 

1-2) LinkedList : 노드 구조로 이루어진 리스트로, 요소의 추가 및 삭제가 빠르다. 반면, 인덱스를 통한 접근 속도는 느리다. 

+-----+------+    +-----+------+    +-----+------+    +-----+------+
|  A  |  *  | -> |  B  |  *  | -> |  C  |  *  | -> |  D  |  *   |
+-----+------+    +-----+------+    +-----+------+    +-----+------+

노드 구조는 각 요소가 객체로 표현되며, 각 노드는 다음 노드에 대한 참조(포인터)를 가지고 있다. 동적으로 크기를 조절할 수 있어, 삽입/삭제가 O(1) 시간 복잡도로 가능하며, 메모리가 필요할 때마다 할당되므로 메모리 낭비가 적다. 하지만, 인덱스를 사용하여 직접 접근할 수 없으므로, 특정 요소에 접근하기 위해서 O(n)이 걸린다. 각 노드가 추가적인 메모리를 사용하므로 메모리 오버헤드가 발생한다. 

 

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class ListExample {
    public static void main(String[] args) {
        // ArrayList 선언 및 초기화
        List<String> arrayList = new ArrayList<>();
        arrayList.add("사과");
        arrayList.add("바나나");
        arrayList.add("바나나");

        // LinkedList 선언 및 초기화
        List<String> linkedList = new LinkedList<>();
        linkedList.add("체리");
        linkedList.add("포도");

        System.out.println("ArrayList: " + arrayList); //["사과", "바나나", "바나나"]
        System.out.println("LinkedList: " + linkedList); //["체리", "포도"]
    }
}

 


2) Set : 중복을 허용하지 않는 데이터의 집합이다. HashSet, LinkedHashSet, TreeSet 등이 있다. 

2-1) HashSet : 해시 테이블을 기반으로 하며, 빠른 검색 성능을 제공한다. 

해시 테이블:
+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 |
+---+---+---+---+---+
|   | A |   | B | C |
+---+---+---+---+---+

해시는 키-값 쌍으로 데이터를 저장하는 구조이다. 해시 함수를 사용하여 키를 해시 값으로 변환하고, 이를 인덱스로 사용하여 데이터를 저장한다. 평균적으로 O(1) 시간 복잡도로 요소에 접근할 수 있습니다. 서로 다른 키가 같은 해시 값을 가질 경우 충돌을 처리해줘야한다. 또한 저장된 데이터 순서를 보장하지 않는다. 그래서 주로 데이터베이스 인덱싱, 캐시 시스템, 중복 제거 등에 사용한다. 

 

2-2) TreeSet : 이진 탐색 트리를 기반으로 하며, 정렬된 순서로 요소를 유지한다. 

       A
      / \
     B   C
    / \   \
   D   E   F

트리는 계층 구조로 데이터를 저장한다. 각 노드는 부모와 자깃 노드로 구성도며, 트리의 최상위 노드를 루트라고 한다. 정렬된 데이터로 상태를 유지하며 데이터 간의 관계를 명확히 표현할 수 있다. 균형잡힌 트리에서는 O(logn) 시간 복잡도로 검색할 수 있다. 

 

3) Queue : FIFO 원칙에 따라 데이터를 처리한다. LinkedList가 큐를 구현할 수 있다. 

      +---+---+---+---+
Front | 1 | 2 | 3 | 4 |
      +---+---+---+---+
Rear

 

먼저 들어온 데이터가 먼저 나가는 구조이고 큐는 주로 대기열을 모델링하는데 사용한다. 큐는 고정크기를 가지고 있으며, 크기를 초과하면 오버 플로우가 발생할 수 있다. 

 

4) Map : map은 키-값 쌍으로 데이터를 저장하는 구조이며, 각 키는 고유하고 키를 통해 해당 값을 빠르게 조회할 수 있따. 중복 키가 없으며 이미 존재하는 키에 값을 추가하면 기존 값이 업데이트 된다. 

 

map:
+-------+-------+
|  키   |  값   |
+-------+-------+
|  'a'  |  1    |
|  'b'  |  2    |
|  'c'  |  3    |
+-------+-------+

 

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.Map;


public class SetExample {
    public static void main(String[] args) {
        // HashSet 선언 및 초기화
        Set<String> hashSet = new HashSet<>();
        hashSet.add("사과");
        hashSet.add("바나나");
        hashSet.add("사과"); // 중복 추가

        // LinkedHashSet 선언 및 초기화
        Set<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add("체리");
        linkedHashSet.add("포도");
        linkedHashSet.add("체리"); // 중복 추가

        System.out.println("HashSet: " + hashSet);
        System.out.println("LinkedHashSet: " + linkedHashSet);
    }
}

public class MapExample {
    public static void main(String[] args) {
        // HashMap 선언 및 초기화
        Map<String, Integer> hashMap = new HashMap<>();
        hashMap.put("사과", 1);
        hashMap.put("바나나", 2);
        hashMap.put("사과", 3); // 키 중복 시 값 업데이트

        // TreeMap 선언 및 초기화
        Map<String, Integer> treeMap = new TreeMap<>();
        treeMap.put("체리", 5);
        treeMap.put("포도", 4);

        System.out.println("HashMap: " + hashMap);
        System.out.println("TreeMap: " + treeMap);
    }
}

 

제너릭(Generic)

: 데이터 타입을 일반화하여 코드의 재사용성을 높이고, 타입 안정성을 제공하는 기능이다. 제너릭을 사용하면 다양한 데이터 타입을 다룰 수 있는 '틀' 을 만들 수 있다. 예를 들어 ArrayList<String> 이라고 하면, 이 리스트는 문자열만 담을 수 있다. 이렇게 하면 나중에 캐스팅 오류 방지할 수 있다.

 

[1]최상위 인터페이스: 자바의 클래스 구조에서 다른 모든 인터페이스의 부모 역할을 하는 인터페이스를 의미한다. 즉, 특정 인터페리스가 다른 인터페이스들의 공통된 특성을 정의하고, 그 아래에 있는 모든 하위 인터페이스가 이 최상위 인터페이스를 상속받는 구조이다. 

반응형

'Java' 카테고리의 다른 글

Java 패키지  (0) 2024.08.27
Java 오버로딩 & 오버라이딩  (0) 2024.08.27
Java 생성자  (0) 2024.08.26
Java 변수 기본형 참조형  (0) 2024.08.26
자바 기초 자료 모음  (1) 2024.08.09