자바의 컬렉션 프레임워크

이원석·2022년 4월 25일
0

Java

목록 보기
7/9
post-thumbnail

0. 프레임워크란


"프레임워크란, 소프트웨어의 구체적인 부분에 해당하는 설계와 구현을 재사용이 가능하게끔 일련의 협업화된 형태로 클래스들을 제공하는 것" -랄프 존슨(Ralph Johnson)-

프레임워크는 어플리케이션을 구현하기 위한 기본적인 뼈대를 의미합니다. 라이브러리는 어플리케이션에서의 기능을 하는 부품을 의미합니다.

자동차를 예를들어 설명하면 한 번 정해진 자동차의 프레임워크, 즉 프레임(뼈대)는 바꾸기 어렵습니다. 소형차의 뼈대로 SUV 차량을 만들 수 없습니다. 하지만 선루프나 헤드라이트등 여러 옵션들, 즉 라이브러르는 쉽게 다른 종류로 변경할 수 있습니다.

자동차의 뼈대(프레임워크) 와 옵션들(라이브러리)는 일일이 만들어서 사용할 수 있지만 굉장히 오랜 시간이 걸릴겁니다. 그렇기 때문에 많은 사람들이 이미 만들어 사용하고 검증된 뼈대(프레임워크) 와 옵션들(라이브러리)을 사용합니다.




1. 자바의 컬렉션 프레임워크


자바의 컬렉션 프레임워크란 다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스의 집합입니다.




1. Map

데이터를 삽입할 때 Key-Value 형태로 삽입되며, Key를 통해 Value를 검색하여 얻을 수 있는 인터페이스

1-1. HashMap - 비동기 처리방식

Map 인터페이스를 상속하고 있습니다. Entry<K, V>의 배열로 저장되며 Key와 Value는 모두 객체입니다. Value 값은 중복 저장될 수 있으며 Key 값은 불가능합니다. 동일한 Key로 Value 값을 저장하게 되면 기존의 Value값은 없어지고 새로운 Value값으로 대치됩니다.

HashMap은 해싱(탐색 키에 hashFuction을 사용하여 바로 탐색 키가 저장될 위치 index를 얻는 것)을 사용하기 때문에 데이터를 검색하는데에 O(1)의 시간복잡도를 가져 탐색속도가 빠릅니다.

해시 함수는 Key 값(큰 수나 문자열) 을 연산을 통해 작은 정수로 매핑시키는(hash address == hash Table index) 역활을 합니다. 따라서 사용자는 그 위치(index)를 알 수 없으며 삽입되는 순서와 들어 있는 위치 또한 관계가 없습니다.

HashMap은 Key, Value에 null값을 허용하지만, HashTable은 null값을 허용하지 않습니다.


1-2. HashTable - 동기 처리방식

HashMap과 비슷한 구조를 가지고 있지만 동기 처리방식과 nullable 형태에서 차이점이 있습니다.


1-3. TreeMap

Map 인터페이스를 상속하고 있습니다. TreeMap은 이진 트리(중 레드블랙 트리)를 기반으로 한 Map 컬렉션입니다. TreeMap은 TreeSet과 다르게 Key와 값이 저장된 Map.Entry 객체를 저장하며, TreeMap에 객체를 저장하면 자동으로 정렬되는데, Key는 저장과 동시에 오름차순으로 정렬됩니다. 부모 Key 값과 비교하여 Key 값이 낮다면 왼쪽 크다면 오른쪽 자식노드에 Map.Entry 객체를 저장합니다.

TreeMap은 데이터를 저장할때 즉시 정렬하기 때문에 추가나 삭제에서 HashMap보다 시간이 더 걸립니다 (시간복잡도 O(logn)). 하지만 정렬된 상태로 Map을 유지해야 하거나 정렬된 데이터를 조회해야 하는 범위 검색이 필요한 경우 TreeMap보다 효율성이 높습니다.


1-3-1. Red-Balck-Tree

레드블랙 트리는, 이진트리의 방식에서 데이터가 한쪽 방면으로만 편향되게 들어올 경우에 치우쳐진 트리가 되어 퍼포먼스가 비효율적으로 되는 경우를 보완하기 위해 사용됩니다. 레드블랙 트리에서는 이렇게 치우쳐진 트리가 형성될 수 없도록 조건이 정해져있습니다.




2. Collection

2-1. List

2-1-1. ArrayList

List 인터페이스를 상속하고 있습니다. ArrayList는 크기가 고정된 List와 달리 새로운 요소가 추가될 때 자동으로 크기를 늘릴수있으며, 크기를 조정할 수 있는 배열입니다. List의 메모리가 낭비되거나 부족한 현상을 해결할 수 있습니다. List와 마찬가지로 단방향 포인터 구조이기 때문에 인덱스를 통해 데이터를 검색합니다.

단점으로는 크기를 변경할 수 없는 배열을 사용하기 때문에 데이터를 삭제하거나 추가할 때, 줄거나 늘어든 만큼의 배열을 생성한 뒤 값을 복사해 옮겨야 하는 복잡한 과정을 거칩니다. 따라서 데이터의 추가와 삭제가 빈번한 상황에서는 비효율적입니다.


2-1-2. LinkedList

List 인터페이스를 상속하고 있습니다. LinkedList는 각 노드가 데이터와 포인터를 가지고 한 줄로 연결되어 있는 방식의 자료구조 입니다.
ArrayList의 경우 하나의 주소 값에 배열을 생성하여 데이터들을 저장하였지만, LinkedList는 데이터가 저장되는 노드들이 모두 주소 값을 가지고있습니다. 각각의 흩어진 노드들은 다음 노드주소를 지목하여(참조) 데이터들 간에 관계를 가지게 됩니다.

LinkedList에서 아래와 같은 상황에 데이터를 추가하게 될 때,

  1. Before 노드 [1 | 0x100]
  2. After 노드 [2 | 0x200]
  3. New 노드 [3 | 0x300]

[1 | 0x100] -> [2 | 0x200]

Before 노드의 Linkfield(0x100)가 New 노드를 가르키게 변경합니다.
[1 | 0x100] -> [3 | 0x300][2 | 0x200]

그 다음 New 노드의 Linkfield(0x300)이 After 노드를 가르키게 변경합니다.
[1 | 0x100] -> [3 | 0x300] -> [2 | 0x200]


데이터가 추가, 삭제될 때 마다 모든 데이터를 새로운 배열에 복사하는 ArrayList 방식보다 LinkedList가 훨신 간결한 과정을 거칩니다.



2-2. Set

2-2-1. HashSet

HashMap과 다르게 중복된 Value값의 저장을 허용하지 않습니다.

HashSet은 객체를 저장하기 전에 객체의 hashCode() 메서드를 호출하여 해시 코드를 얻어낸 다음, 저장되어 있는 객체들의 해시 코드와 비교를 합니다. 만약 같은 해시 코드가 있다면 equals()메서드로 두 객체를 비교 한 후, True값이 나온다면 동일한 객체로 판단하고 중복 저장을 하지 않습니다.

문자열이 HashSet에 저장될 때, 같은 문자열을 갖는 String 객체는 동일한 객체로 간주되는 이유가 있습니다. 같은 문자열이라도 hashCode()의 리턴값이 다를 수 있는데, String 클래스가 hashCode()와 equals() 메서드를 오버라이딩하여 같은 문자열의 경우 hashCode()의 리턴 값을 같게하고 equals()의 두 객체 비교에서 True값이 나오도록 했기 때문입니다.

2-2-2. TreeSet

2-2-3. LinkedHashSet





[참고문헌]
https://github.com/WeareSoft/tech-interview/blob/master/contents/java.md
https://coding-factory.tistory.com/556
https://moolgogiheart.tistory.com/87
https://mattlee.tistory.com/62
https://coding-factory.tistory.com/557
https://zeddios.tistory.com/237
https://kimvampa.tistory.com/79
https://crazykim2.tistory.com/474

0개의 댓글