15. [Java] 컬렉션(Collection) 2 / 20230502
🧑🏻💻 TIL(Today I Learned)
🧑🏻💻 컬렉션 프레임워크
1. 컬렉션 프레임워크(Collection Framework)
➡️ 여러 데이터를 그룹으로 묶어놓은 것이 컬렉션, 이러한 컬렉션을 다루는 데 있어 편리한 미리 정의해 놓은 것
➡️ 특정 자료 구조에 데이터를 추가하고, 삭제하고, 수정하고, 검색하는 등 동작을 수행하는 편리한 메서드 제공
🔎 주요 인터페이스 세 가지
- List
- 데이터의 순서가 유지되며 중복 저장이 가능한 컬렉션을 구현하는 데 사용
- ArrayList, Vector, Stack, LinkedList 등이 List 컬렉션 구현
- Set
- 데이터의 순서가 유지되지 않으며 중복 저장 불가능한 컬렉션을 구현하는 데 사용
- HashSet, TreeSet 등이 Set 인터페이스 구현
- Map
- 키(Key)와 값(value)의 쌍으로 데이터를 저장하는 컬렉션을 구현하는 데 사용
- 데이터의 순서가 유지되지 않으며 키는 값을 식별하기 위해 사용되므로 중복 저장이 불가능하지만 값은 중복 저장 가능
👉🏻 List와 Set은 공통점이 많아 Collection이라는 인터페이스로 묶임
👉🏻 즉, 이 둘의 공통점이 추출되어 추상화된 것이 바로 Collection 인터페이스
🔎 Collection 인터페이스
2. List<E>
➡️ 배열과 같이 객체를 일렬로 늘어놓은 구조
➡️ 객체를 인덱스로 관리하기 때문에 객체를 저장하면 자동으로 인덱스가 부여되고, 인덱스로 객체를 검색 추가 삭제할 수 있는 등의 여러 기능 제공
➡️ 컬렉션 인터페이스의 메서드 또한 상속받아 사용가능
🔎 ArrayList
➡️ List 인터페이스를 구현한 클래스, 컬렉션 프레임워크에서 가장 많이 사용됨
➡️ List 인터페이스를 구현하므로 저장 순서가 유지되고 중복 허용(데이터의 저장공간으로 배열 사용)
➡️ 객체를 추가하면 객체가 인덱스로 관리됨
→ 배열은 생성될 때 크기가 고정되며 크기를 변경할 수 없지만 ArrayList 는 저장 용량을 초과하여 객체들이 추가되면 자동으로 저장 용량이 늘어나게 됨
➡️ List 계열의 자료구조의 특성을 이어받아 데이터가 연속적으로 존재함 : 데이터의 순서 유지
ArrayList<타입 매개변수> 객체명 = new ArrayList<타입 매개변수>(초기 저장 용량);
ArrayList<String> container1 = new ArrayList<String>();
// String 타입의 객체를 저장하는 ArrayList 생성
// 초기 용량이 인자로 전달되지 않으면 기본적으로 10으로 지정됩니다.
ArrayList<String> container2 = new ArrayList<String>(30);
// String 타입의 객체를 저장하는 ArrayList 생성
// 초기 용량을 30으로 지정하였습니다.
- 객체를 추가하면 인덱스 0부터 차례대로 저장됨
→ 특정 인덱스의 객체를 제거하면 바로 뒤 인덱스부터 마지막 인덱스까지 모두 앞으로 1 씩 당겨짐 - 빈번한 객체 삭제와 삽입이 일어나는 곳에서는 LikedList 사용하는 것이 좋음
🔎 LinkedList
➡️ 데이터를 효율적으로 추가, 삭제, 변경하기 위해 사용
➡️ 배열에는 모든 데이터가 연속적으로 존재하지만 LinkedList에는 불연속적으로 존재하며 이 데이터는 서로 연결(Link) 되어 있음
➡️ 배열은 구조가 간단하고 데이터를 읽는 데 걸리는 시간이 짧지만 크기를 변경할 수 없고 비순차적인 데이터의 추가 삭제에 시간이 많이 걸린다는 단점이 있음
✍🏻 그걸 보완하는 것이 "LinkedList"
➡️ 불연속적으로 연결되어 있는 것 → 노드를 하나하나 연결하고 있음
class Node {
Node next; // 다음 노드를 찾아갈 수 있는 참조변수 가지고 있음
Object obj; // 데이터
}
// 데이터의 삭제 : 단 한 번의 참조변경만으로 가능
// 데이터의 추가 : 한번의 node 객체 생성과 두 번의 참조변경만으로 가능
➡️ 단점 : 데이터 접근성이 나쁨 (한 번에 가는 게 안 됨) ※ 이런 단점을 개선한 것이 : 이중 연결 리스트
📍 이중 연결 리스트(doubleLinkedList) -> 연결이 두 개 (자바는 이렇게 구현)
class Node {
Node next; // 다음 노드 참조변수
Node previous; // 이전 노드 참조변수
Object obj;
}
// 접근성 향상, 앞뒤로 이동가능하지만 배열에 비하면 아직 성능 좋지 않음
ArrayList(배열 기반, 연속적) vs LinkedList(연결 기반, 불연속적) => 성능 비교
1. 순차적으로 데이터를 추가/ 삭제 - ArrayList가 빠름
2. 비순차적으로 데이터를 추가/ 삭제(중간 추가/삭제) - LinkedList가 빠름
3. 접근 시간 - ArrayList가 빠름
3. Iterator
➡️ 컬렉션에 저장된 요소들을 순차적으로 읽어오는 역할
➡️ Collection 인터페이스에 정의된 iterator()를 호출하면 Iterator 타입의 인스턴스 반환됨
➡️ Collection 인터페이스를 상속받는 List와 Set 인터페이스를 구현한 클래스들은 iterator() 메서드 사용가능
ArrayList<String> list = ...;
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){ // 다음 객체가 있다면
String str = iterator.next(); // 객체를 읽어오고,
if(str.equals("str과 같은 단어")){ // 조건에 부합한다면
iterator.remove(); // 해당 객체를 컬렉션에서 제거합니다.
}
}
// hasNext()에서 true가 리턴될 때만 next() 메서드가 동작하도록 코드를 작성하는 것이 좋음
// next()메서드로 가져온 객체를 컬렉션에서 제거하고 싶다면 remove() 메서드 호출
// remove()메서드는 컬렉션에서 실제로 객체 삭제함
--------------------------------------------------------------
ArrayList<String> list = ...;
for(String str : list) {
...
}
//Iterator 사용하지 않더라도 for-each 문 이용해 전체 객체 대상으로 반복 가능
4. Set<E>
➡️ 집합을 의미, 중복된 값을 허용하지 않음, 저장 순서를 유지하지 않는 컬렉션
🔎 HashSet
➡️ Set 인터페이스를 구현한 가장 대표적인 컬렉션 클래스
➡️ 중복된 값을 허용하지 않으며 저장 순서 유지하지 않음
➡️ 값을 추가할 때 해당 값이 중복된 값인지 판단하는 법
- add(Object o) 통해 객체 저장
- 이때 저장하고자 하는 객체의 해시코드를 hashCode() 메서드로 얻어냄
- Set이 저장하고 있는 모든 객체의 해시코드를 HashCode() 메서드로 얻어냄
- 저장하고자 하는 객체의 해시코드와, Set에 이미 저장되어 있던 객체들의 해시코드 비교하여 같은 해시코드 있는지 검사
- 만약 같은 해시코드를 가진 객체가 존재한다면 5번으로
- 같은 해시코드를 가진 객체가 존재하지 않는다면, Set에 객체 추가되고 add(Object o) 메서드가 true 리턴
- equals() 메서드 통해 객체 비교
- true가 리턴 된다면 중복 객체로 간주하여 Set에 추가되지 않고 add(Object o)가 false 리턴
- false가 리턴된다면 Set에 객체가 추가되며 add(Object o) 메서드가 true 리턴
📍 "Java"가 중복되니 한 번만 출력되고 마지막 "Java"는 출력되지 않음
🔎 TreeSet
➡️ 이진 탐색 트리 형태로 데이터 저장
➡️ 데이터의 중복 저장을 허용하지 않고 저장 순서를 유지하지 않는 Set 인터페이스의 특징 유지
이진 탐색 트리(Binary Search Tree)란?
👉🏻 하나의 부모 노드가 최대 두 개의 자식 노드와 연결되는 이진트리의 일종, 정렬과 검색에 특화됨
class Node {
Object element; // 객체의 주소값을 저장하는 참조변수
Node left; // 왼쪽 자식 노드의 주소값을 저장
Node right; // 오른쪽 자식 노드의 주소값을 저장
}
- 모든 왼쪽 자식의 값이 루트나 부모보다 작고 모든 오른쪽 자식의 값이 루트나 부모보다 큰 값을 가지는 게 특징
5. Map<K, V>
➡️ Map 인터페이스는 키와 값으로 구성된 객체를 저장하는 구조로 되어있음
➡️ 객체는 Entry 객체라고 하는데 이 Entry 객체는 키와 값을 각각 Key 객체와 Value 객체로 저장함
➡️ 키는 중복으로 저장될 수 없지만 값은 중복 저장 가능
👉🏻 키의 역할이 값을 식별하는 것이기 때문에
➡️ 만약 기존에 저장된 키와 같은 키로 값을 저장하면 기존의 값이 새로운 값으로 대치됨
🔎 HashMap
➡️ Map 인터페이스를 구현한 대표적인 클래스
➡️ 키와 값으로 구성된 객체 저장 Entry 객체
➡️ 해시 함수를 통해 키와 값이 저장되는 위치를 결정하므로 사용자는 그 위치를 알 수 없고 삽입되는 순서와 위치 또한 관계 없음
➡️ 해싱(Hashing)을 사용하기 때문에 많은 양의 데이터를 검색하는 데 있어 뛰어난 성능 보여줌
HashMap<String, Integer> hashmap = new HashMap<>();
// 키와 값의 타입을 따로 지정해야함
→ Map은 키와 값을 쌍으로 저장하기 때문에 iterator()를 직접 호출할 수 없음
대신 keySet() 이나 entrySet() 메서드 이용해 Set 형태로 반환된 컬렉션에 iterator() 호출하여 반복자를 만든 후 반복자를 통해 순회가능
- keySet() : 모든 키를 set 객체에 담아서 리턴(Set 타입)
- entrySet() : 키와 값의 쌍으로 구성된 모든 Map.Entry 객체를 Set에 담아서 리턴
🔎 HashTable
➡️ HashMap과 내부 구조 동일, 사용방법 유사, 스레드와 관련
➡️ HashMap이 HashTable의 새로운 버전이라고 할 수 있음
컬렉션 대장정 끝! 코플릿도 여러 번 풀어봐야겠다 메서드는 다 외울 수 없으니 최대한 친해져야 할 듯!!
'SEB_BE_45 > 공부 정리' 카테고리의 다른 글
16. [Java] Annotation, 람다식, 스트림 / 20230503 (1) | 2023.05.09 |
---|---|
16. [Java] Annotation, 람다식, 스트림 / 20230503 (0) | 2023.05.08 |
14. [Java] 컬렉션 (Collection) 1 / 20230501 (0) | 2023.05.02 |
13. 객체지향프로그래밍의 심화 / 20230428 (0) | 2023.04.29 |
12. 객체지향프로그래밍의 심화 / 20230427 (0) | 2023.04.27 |