JAVA 컬렉션

금송·2024년 9월 26일
0

이론

목록 보기
19/26
post-thumbnail

컬렉션

컬렉션의 사전적 의미는 요소를 수집해서 저장하는 것

프로그래밍을 하다보면 다수개의 객체를 저장해 두고 필요할 때 마다 꺼내서 사용하는 경우

가장 간단한 방법 - 배열

배열은 쉽게 생성하고 사용할 수 있지만, 저장할 수 있는 객체 수가 배열을 생성할 때 결정되기 때문에 불특정 다수의 객체를 저장하기에는 문제가 있다.

이때 자바는 배열의 이런 문제점을 해결하고, 널리 알려져 있는 자료구조를 바탕으로 객체들을 효율적으로 추가,삭제,검색할 수 있도록 java.util 패키지에 컬렉션과 관련된 인터페이스와 클래스들을 포함시켜 놓았는데 이들을 총칭해서 컬렉션 이라 부른다.

  • List 인터페이스를 구현한 클래스 : ArrayList, Vector, LinkedList
  • Set 인터페이스를 구현한 클래스 : HashSet, TreeSet
  • Map 인터페이스를 구현한 클래스 : HashMap, HashTable, TreeMap, Properties

List와 Set은 객체를 추가, 삭제, 검색하는 방법에 많은 공통점이 있는데 이 인터페이스들의 공통된 메소드만 모아 Collection 인터페이스로 정의해두고 있다.

Map은 키(Key)와 값(Value)을 하나의 쌍으로 묶어서 관리하는 구조로 되어 있지만 List와 Set과는 자료구조의 사용 방법이 전혀 다름.

LIst, Set, Map의 특징

Set의 중복 저장 불가가 중요한 부분

List - ArrayList, LinkedList

List

List 컬렉션은 객체를 일렬로 늘어놓은 구조

배열도 같은 특징을 가지고 있지만, 배열은 선언 시점에 저장할 수 있는 크기가 결정이 되기 때문에 명확하지 않은 경우에 선언하기가 어려운 단점이 있다.

그걸 보완한, 자료형의 개수가 계속 변하는 상황에서 유리한 자료구조 형태가 바로 List 이다.

기능메소드설명
객체 추가boolean add(E e)주어진 객체를 맨 끝에 추가
void add(int index, E element)주어진 인덱스에 객체를 추가
set(int index, E element)주어진 인덱스에 저장된 객체를 주어진 객체로 바꿈
객체 검색boolean contains(Object o)주어진 객체가 저장되어있는지 여부
E get(int index)주어진 인덱스에 저장된 객체를 리턴
isEmpty()컬렉션이 비어있는지 여부
int size()저장되어 있는 전체 객체 수 리턴
객체 삭제void clear()저장된 모든 객체를 삭제
E remove(int index)주어진 인덱스에 저장된 객체를 삭제
boolean remove(Object o)주어진 객체를 삭제

시간 복잡도 : 효율성

ArrayList - O(N), 상수시간복잡도. 최악의 경우

LinkedList - O(1), 상수시간복잡도. 상당히 빠름

ArrayList

ArrayList

  • 기본 생성자로 ArrayList 를 생성하면 내부에 10개의 객체를 저장할 수 있는 초기 용량을 가진다
  • 저장하는 객체의 수가 증가하면 자동으로 용량이 증가한다
  • 처음부터 용량을 정의하고 싶으면 크기를 매개값으로 넣은 생성자를 생성
  • 검색이 잦은 작업에 용이

ArrayList 객체 삭제 시 매커니즘

LinkedList

ArrayList는 내부 배열의 객체를 인덱스로 관리

LinkedList는 인접 참조를 링크하여 체인형식으로 관리

삽입과 삭제등 내부 배열 객체의 수정이 잦은 작업에 용이

ArrayList 실습

package chap11.list;

import java.util.*; // util 내에 있어서 전체 임포트

public class ArrayListExample {
    public static void main(String[] args) {
        // ArrayList 값 추가
        List<String> list = new ArrayList<>(); // 디폴트로 10개의 공간이 있는 배열이 할당됨. 이때 객체를 추가하면 추가한 갯수만큼 배열 생성
        list.add("Java");
        list.add("Spring");
        list.add("Servlet/JSP");
        list.add("DBMS");
        list.add("JPA");

        // 추가된 값 총 개수
        System.out.println("총 개수 : " + list.size());

        // 값 순회하면서 출력
        for (int i = 0; i < list.size(); i++) {
            System.out.println("\t" + i + " : " + list.get(i));
        }

        // 값 삭제
        list.remove(2);
        list.remove(2);
        list.remove("Java");

        // 총 개수 출력
        System.out.println("총 개수 : " + list.size());

        // 향상된 for문으로 순회하면서 값 출력
        for (String element : list) {
            System.out.println("\t" + list + " : " + element);
        }
    }
}

LinkedList 실습

package chap11.list;

import java.util.*;

public class LinkedListExample {
    public static void main(String[] args) {
        // List의 구현체여서 이름만 바꿔줘도 사용 가능
        List<String> list = new LinkedList<>();
        list.add("Java");
        list.add("Spring");
        list.add("Servlet/JSP");
        list.add("DBMS");
        list.add("JPA");

        // 추가된 값 총 개수
        System.out.println("총 개수 : " + list.size());

        // 값 순회하면서 출력
        for (int i = 0; i < list.size(); i++) {
            System.out.println("\t" + i + " : " + list.get(i));
        }

        // 값 삭제
        list.remove(2);
        list.remove(2);
        list.remove("Java");

        // 총 개수 출력
        System.out.println("총 개수 : " + list.size());

        // 향상된 for문으로 순회하면서 값 출력
        for (String element : list) {
            System.out.println("\t" + list + " : " + element);
        }
    }
}

속도 체크

package chap11.list;

import java.util.*;

public class LinkedListExample {

    public static void main(String[] args) {
        List<String> arrayList = new ArrayList<>();
        List<String> linkedList = new LinkedList<>();

        long startTime;
        long endTime;

        startTime = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            arrayList.add(0, String.valueOf(i));
        }
        endTime = System.nanoTime();
        System.out.println("ArrayList 걸린시간: " + (endTime - startTime) + "ns");

        startTime = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            linkedList.add(0, String.valueOf(i));
        }
        endTime = System.nanoTime();
        System.out.println("LinkedList 걸린시간: " + (endTime - startTime) + "ns");
    }
}

// 결과
ArrayList 걸린시간: 3211300ns
LinkedList 걸린시간: 1221000ns

Set - HashSet

List 컬렉션은 저장 순서를 유지하지만, Set 컬렉션은 저장 순서가 유지되지 않음.

또한 객체를 중복해서 저장할 수 없다는 큰 특징이 있습니다.

기능메소드설명
객체 추가boolean add(E e)주어진 객체를 저장, 객체가 성공적으로 저장되면 true를 리턴하고 중복 객체면 false를 리턴
객체 검색boolean contains(Object o)주어진 객체가 저장되어 있는지 여부
isEmpty()컬렉션이 비어 있는지 조사
Iterator iterator()저장된 객체를 한 번씩 가져오는 반복자 리턴
int size()저장되어 있는 전체 객체 수 리턴
객체 삭제void clear()저장된 모든 객체를 삭제
boolean remove(Object o)주어진 객체를 삭제

Iterator(반복자) 인터페이스에 선언된 메소드

Set<String> set = ...;
Iterator<String> iterator = set.iterator();
리턴 타입메소드명설명
booleanhasNext()가져올 객체가 있으면 true를 리턴하고 없으면 false를 리턴합니다
Enext()컬렉션에서 하나의 객체를 가져옵니다
voidremove()Set 컬렉션에서 객체를 제거합니다

Set 인터페이스는 중복처리를 한다. 중복인 객체는 저장하지 않는다.

해당 내용의 매커니즘

Map - HashMap, HashTable

  • 키 (key)와 값 (value)으로 구성된 객체를 저장하는 구조
    • 키와 값은 모두 객체
  • 키는 중복될 수 없지만, 값은 중복 저장이 가능하다
  • 만약 기존에 저장되어있던 키값과 동일한 키값이 저장되면 기존의 값은 없어지고 새로운 값으로 대체된다.

  • Map 컬렉션 - HashMap, HashTable, LinkedHashMap, Properties, TreeMap 등

Map 인터페이스에서 제공하는 메소드

기능메소드설명
객체추가V put(K key, V value)주어진 키와 값을 추가, 저장되면 값을 리턴
객체검색boolean containsKey(Object key)주어진 키가 있는지 여부
boolean containsValue(Object value)주어진 값이 있는지 여부
Set(Map.Entry<K,V>> entrySet()키와 값의 쌍으로 구성된 모든 Map.Entry 객체를 Set에 담아서 리턴
V get(Object key)주어진 키가 있는 값을 리턴
boolean isEmpty()컬렉션이 비어 있는지 여부
Set keySet()모든 키를 Set 객체에 담아서 리턴
int size()저장된 키의 총 개수 리턴
Collection values()저장된 모든 값을 Collection에 담아서 리턴
객체삭제vold clear()모든 Map.Entry(키와 값)를 삭제
V remove(Object key)주어진 키와 일치하는 Map.Entry를 삭제하고 값을 리턴
  • Key 값으로 객체를 관리하기 때문에 Key 값을 매개값으로 갖는 메소드가 많음
  • Map 인터페이스의 제네릭 타입 파라미터 : K, V
Map<String, Integer> map = ...;
map.put("홍길동", 30);          // 객체 추가
int score = map.get("홍길동");  // 객체 찾기
map.remove("홍길동");           // 객체 삭제

저장된 객체 전체를 하나씩 읽는 메소드

KeySet()

  • 모든 키를 Set 컬렉션으로 얻은 다음, 반복자를 통해 키를 하나씩 얻고 get() 메소드를 통해 값을 얻음
Map<K, V> map = ...;
Set<K> keySet = map.keySet();
Iterator<K> keyIterator = keySet.iterator();
while(keyIterator.hasNext()) {
	K key = keyIterator.next();
	V value = map.get(key);
}

entrySet()

  • 모든 Map.Entry를 Set으로 얻은 다음, 반복자를 통해 Map.Entry를 하나씩 얻고 getKey()와 getValue()  메소드를 이용해 키와 값을 얻음
Set<Map.Entry<String, Object>> entries = map.entrySet();
for (Map.Entry<String, Object> entry : entries) {
	String key = entry.getKey();
	Object value = entry.getValue();
}

HashTable()

  • HashMap과 동일한 내부 구조를 가짐
  • HashMap과 다른 점
    • 동기화(synchronized)된 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 이 메소드를 실행할 수 없고, 하나의 스레드가 실행을 완료해야 다른 스레드를 실행할 수 있다
    • 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제할 수 있다
    • thread safe

Stack / Queue

후입선출 (LIFO : Last In First Out)

  • 나중에 넣은 객체가 먼저 빠져나가는 구조
  • Stack

선입선출 (FIFIO : First In First Out)

  • 먼저 넣은 객체가 먼저 빠져나가는 구조
  • Queue

Stack

  • 후입선출 (LIFO)
  • 마지막에 넣은 객체가 가장 먼저 빠지는 자료구조

Stack 인터페이스의 주요 메소드

리턴 타입메소드설명
Epush(E item)주어진 객체를 스택에 넣는다
Epeek()스택의 맨 위 객체를 가져온다. 객체를 스택에서 제거하지 않는다.
Epop()스택의 맨 위 객체를 가져오고, 객체를 스택에서 제거한다.
Stack<E> stack = new Stack<E>(); // 스택 객체 생성

Queue

  • 선입선출 (FIFO)
  • 앞서 들어간 데이터가 먼저 출력이 되는 자료구조

Queue 인터페이스의 주요 메소드

리턴 타입메소드설명
booleanoffer(E e)주어진 객체를 넣는다.
Epeek()객체 하나를 가져온다. 객체를 큐에서 제거하지 않는다.
Epoll()객체 하나를 가져온다. 객체를 큐에서 제거한다.
Queue<E> queue = new LinkedList<E>(); // 큐 객체 생성
  • Queue 인터페이스를 구현한 대표적인 클래스 : LinkedList
profile
goldsong

0개의 댓글

관련 채용 정보