✏️ Java Collection

박상민·2023년 9월 20일
0

개념 정리!

목록 보기
4/18
post-thumbnail

컬렉션(collection)은 많은 데이터 요소를 효율적으로 관리하기 위한 자료구조를 말하며, ArrayList, LinkedList, HashMap 등이 여기에 포함됩니다. 그리고 이 컬렉션들은 제네릭(generics) 형식으로 구현되어 있어 컬렉션과 함께 제네릭에 대해서도 알아둘 필요가 있다.

⭐️ Collection Freamwork?

다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스의 집합을 의미한다.
즉, 데이터를 저장하는 자료 구조와 데이터를 처리하는 알고리즘을 구조화하여 클래스오 구현해 놓은 것을 말한다. 컬렉션 프레임워크는 자바의 인터페이스를 사용하여 구현된다.

💡 데이터를 담고 처리하는 방법에는 배열(Array)이 있는데 왜 Collection을 사용할까?
배열은 정적 메모리 할당을 사용하지만 컬렉션은 동적 메모리 할당을 한다.
예를 들어 배열은 new int[4]를 하면 4개 공간밖에 못쓰고 미리 선얼을 통해 4개의 공간을 만들어야한다.(정적 메모리)
Collection은 공간이 계속 필요한 만큼 추가할 수 있다.(동적 메모리)

📌 Collection intetface의 주요 인터페이스

자바에서의 자료구조 유형은 다음과 같다,

  • List: 순서가 있는 유형
  • Set: 순서가 중요하지 않은 유형
  • Queue: 먼저 들어온 것이 먼저 나가는 유형
  • Map: Key-Value 형태로 저장되는 유형


4개의 자료구조 유형 중 List, Set, Queue 인터페이스는 모두 Collection 인터페이스(java.util.Collection)를 상속받지만, 구조상의 차이로 인해서 Map 인터페이스(java.util.Map)는 별도로 정의된다.
따라서 List, Set, Queue 인터페이스의 공통된 부분을 Collection 인터페이스에서 정의하고 있고, Map 인터페이스의 경우 Collection 인터페이스를 상속받고 있지 않지만 Collection으로 분류된다.

Collection 인터페이스와 Map 인터페이스는 자바 컬렉션 클래스의 주요 '루트' 인터페이스이다.

📌 Collection intetface 특징

컬렉션 클래스들이 데이터를 다룰 때 그 데이터는 기본적으로 객체만 가능하다. 따라서 char, int, float와 같은 기본형은 사용할 수 없고 대신 Wrapper클래스를 사용해야 한다. 하지만, 오토박싱(auto boxing)과 오토언박싱(auto unboxing)으로 인해 사용자는 마치 기본형을 다룰 수 있는 것처럼 사용할 수 있다.

컬렉션과 관련된 인터페이스 또는 클래스가 정의되어 있는 코드를 살펴보면 아래와 같이 제네릭(generics) 형태로 구현되어 있는 것을 확인할 수 있다.. 따라서 사용자는 사용하고자 하는 데이터 타입을 지정하여 사용할 수 있다.

public interface List<E> extends Collection<E> {  ...  }

✔︎ List interface

중복되는 데이터들을 저장해야 할 때, 배열에 들어간 순서를 유지하고 싶을 때 사용한다. (중복 O, 순서 O)

List 인터페이스는 Collection의 다른 인터페이스들과 가장 큰 차이는 배열처럼 순서가 있다는 것이다.
List 인터페이스에서 ArrayList, LinkedList, Vector, Stack 순서로 가장 많이 사용된다.

ArrayList와 Vector 클래스는 거의 동일하지만 차이점이 있다.

  • ArrayList는 Thread safe X
    • 객체에 여러 명이 달려들어 값을 변경하려고 하면 문제가 발생할 수 있다.
  • Vector는 Thread safe O
  • ArrayList

    • 단방향 포인터 구조로 각 데이터에 대한 인덱스를 가지고 있어 조회 기능에 성능이 뛰어나다.

    • 검색이 빠르다. 순차적으로 데이터가 추가된다면 빠르다.

    • 하지만 List들의 중간중간 데이터에 빈번한 추가 삭제가 일어난다면 느리다.

    • List 컬렉션을 여러 스레드에서 공유해야 한다면 Thread safe 하지 않다.

  • LinkedList

    • 양방향 포인터 구조로 데이터의 삽입, 삭제가 빈번할 경우 데이터의 위치정보만 수정하면 되기에 좋은 성능을 발휘한다.

    • 하지만 검색이 느리다.

    • 스택, 큐, 양방향 큐 등을 만들기 위한 용도로 쓰임

  • Vector

    • 과거에 대용량 처리를 위해 사용했고, 내부에서 자동으로 동기화 처리가 일어나 비교적 성능이 좋지 않고 무거워 최근에는 잘 쓰이지 않는다

    • ArrayList와 내부 구조는 동일하지만 Thread safe 하다.

✔︎ Set interface

순서가 필요 없고, set에 저장될 데이터가 중복이 되면 안 될 때 사용한다. (중복 x, 순서 x)

순서를 유지하지 않는 데이터의 집합으로 데이터의 중복을 허용하지 않는다. (단, LinkedHashSet은 순서를 보장한다.)

  • HashSet

    • 가장 빠른 임의 접근 속도

    • 순서를 예측할 수 없다.

    • Thread safe 하지 않다.

  • TreeSet

    • 정렬방법을 지정할 수 있다. (기본은 오름차순 정렬)

    • Thread safe 하지 않다.

LinkedHashSet

  • 입력된 순서대로 저장한다.
  • Thread safe 하지 않다.

✔︎ Map interface

데이터를 저장할 때, key-value로 저장하고 싶을 때, 그리고, key를 중복 저장하고 싶지 않을 때 사용한다.

  • key 중복 x
  • value 중복 o
  • 순서 x

Map은 키(Key)와 값(value)으로 이루어진 데이터 집합이다.

Map의 주요 특징

  • 모든 데이터는 키와 값이 존재한다.

  • 항상 Key-Value 쌍을 유지한다.

  • 키는 해당 Map에서 고유해야한다.

  • 값은 해당 Map에서 중복되어도 전혀 상관없다.

  • 데이터 추가 순서는 중요하지 않다.

    • 데이터를 저장한 순서대로 결과가 출력되지 않는다.
  • Hashtable

    • HashMap보다는 느리지만 동기화 지원
    • null불가
    • Thread safe
  • HashMap

    • 중복과 순서가 허용되지 않으며 null값이 올 수 있다.

    • 대부분 HashMap 객체를 생성할 때에는 매개 변수가 없는 생성자를 사용한다.

      • HashMap에 담을 데이터의 개수가 많은 경우에는 초기 크기를 지정해주는 것을 권장한다.
    HashMap<String, String> map = new HashMap<String, String>();
  • TreeMap

    • 키와 값을 저장하는 동시에 키를 정렬한다.

    • 키(key)가 정렬되어 저장되기 때문에 검색 시 빠르다.

    • 오름차순으로 정렬되며, 정렬되는 순서는 숫자 > 알파벳 대문자 > 알파벳 소문자 > 한글 순이다.

    • 정렬을 해야 할 필요가 있다면 HashMap 보다는 TreeMap을 사용하는 것이 더 유리하다.

    TreeMap<String, String> treeMap = new TreeMap<String, String>();

📌 제네릭(Generics)이란?

제네릭(generics)은 한 번의 정의로 여러 종류의 데이터의 타입을 다룰 수 있도록 하는 방법을 말한다. 예를 들어 아래와 같이 ArrayList 형태로 클래스가 정의되어 있다고 하자.

public class ArrayList<E> extends AbstractList<E>
           implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
   ...
}

이때 사용자는 데이터로 String을 사용할 때는 ArrayList으로, Integer를 사용할 때는 ArrayList로 지정하여 사용할 수 있다.

//예시
ArrayList<String> a1 = new ArrayList<String>();
ArrayList<Integer> a1 = new ArrayList<Integer>();

이처럼 사용자가 사용시에 데이터 타입을 지정하게 되면 컴파일 단계에서 데이터 타입을 미리 체크할 수 있는 장점이 있다.


출처
https://choicode.tistory.com/25
https://kadosholy.tistory.com/117
https://crazykim2.tistory.com/557

profile
스프링 백엔드를 공부중인 대학생입니다!

0개의 댓글