| 컬렉션 프레임워크란?
객체들을 효율적으로 추가, 삭제, 검색 할 수 있도록 인터페이스와 구현 클래스를 java.utill 패키지에서 제공하는데 이것을 컬렉션 프레임워크(Collection Framework) 라고 한다.
객체 저장소로서 배열을 사용할 수도 있지만 배열은 선언 시 크기를 정해야하고, 또 정한 크기를 변경할 수 없을 뿐만 아니라 항목을 저장, 삭제, 추가하는 메소드가 없기 대문에 인덱스를 사용해야 하는 번거로움이 있다.
이를 대신해 컬렉션 프레임워크를 사용한다.
컬렉션 프레임워크의 주요 인터페이스로는 List, Set, Map이 있다.
| List 컬렉션
List 컬렉션은 배열과 비슷하게 인덱스를 관리하지만, 차이점으로 이러한 특징이 있다.
1. 저장용량이 자동으로 증가
2. 저장 시 자동 인덱스 부여
3. 추가, 삭제, 검색 등 다양한 메소드 제공
4. 중복 저장 O
5. Null 저장 O
List 컬렉션은 객체 자체를 저장하는 것이 아닌 객체의 번지를 참조하기 때문에동일한 객체를 중복 저장 할 수 있다. 이런 경우는 동일한 번지가 참조된다. null 저장 하는 경우 해당 인덱스는 객체를 참조하지 않는다.
A. 메소드 종류
add(E e) | 객체를 맨 끝에 추가 |
add(Index ,E e) | 해당 인덱스에 객체 추가 |
set(Index, E e) | 해당 인덱스에 저장된 객체를 주어진 객체로 바꿈 |
contains(object o) | 해당 객체가 저장 되어있는지 확인 |
get(index) | 해당 인덱스에 저장된 객체를 리턴 |
isEmpty() | 컬렉션이 비어있는지 확인 |
size() | 저장 되어있는 전체 객체 수 리턴 (=길이) |
clear() | 저장된 모든 객체 삭제 |
remove(index) | 해당 인덱스에 저장된 객체 삭제 |
remove(object o) | 주어진 객체 삭제 |
ArrayList 로 선언했다고 했을 때 대표적인 메소드 예시.
List<String> list = new ArrayList<>();
list.add("전원우"); // 맨 끝 객체 추가
list.add(1,"부승관"); // 인덱스 1에 객체 삽입
String str = list.get(1); // 인덱스로 객체 검색
list.remove(0); // 인덱스로 객체 삭제
list.remove("부승관"); // 객체 삭제
B. ArrayList
List의 대표적인 구현 클래스이다.
선언 방법 :
List<String> list = new ArrayList<>();
10개의 객체를 저장할 수 있는 초기용량을 가지며, 저장되는 객체수가 늘어남에 따라 용량이 자동으로 증가 한다.
추가 : 0번 인덱스부터 차례대로 저장된다.
삭제 : 바로 뒤 인덱스부터 마지막 까지 앞으로 1씩 당겨진다.
삽입 : 바로 뒤 인덱스부터 마지막 까지 뒤로 1씩 밀려난다.
때문에 빈번한 삭제, 삽입이 일어나는 경우에는 Arraylist가 적합하지 않다.
C. LinkedList
ArrayList와 사용방법은 동일하지만 다른 내부구조를 가지고 있다.
ArrayList가 내부 배열에 객체를 저장해서 관리한다면
LinkedList는 인접 참조를 링크해서 체인처럼 관리한다.
객체를 삽입이나 삭제 할 때, 앞 뒤 링크만 변경되고 나머지 링크는 변경되지 않는다. (아래 그림 참조)
선언 방법 :
List<String> list = new LinkedList<>();
순차적으로 추가/삭제가 많은 경우 -> ArrayList
중간에 추가/삭제가 많은 경우 -> LinkedList
검색을 많이 하는 경우 -> ArrayList
| Set 컬렉션
List 컬렉션은 객체 저장 순서를 유지한다면
Set 컬렉션은 저장 순서가 유지되지 않는다.
1. 저장 순서가 유지 X
2. 중복 저장 X
3. 하나의 Null만 저장 O
4. 인덱스가 없다
A. 메소드 종류
add(E e) | 주어진 객체를 저장. 성공적으로 저장 -> true 중복 객체 -> false 리턴 |
contains(object o) | 해당 객체가 저장 되어있는지 확인 |
isEmpty() | 컬렉션이 비어있는지 확인 |
Iterator<E> iterator() | 저장된 객체를 한 번 씩 가져오는 반복자를 리턴 |
size() | 저장 되어있는 전체 객체 수 리턴 (=길이) |
clear() | 저장된 모든 객체 삭제 |
remove(object o) | 주어진 객체 삭제 |
HashSet 으로 선언했다고 했을 때 대표적인 메소드 예시.
Set<String> set = new HashSet<>();
set.add("전원우"); // 객체 추가
set.add("부승관");
set.remove("부승관"); // 객체 삭제
Iterator iterator()
Set은 인덱스가 없기 때문에 인덱스로 객체를 검색해서 가져오는 메소드가 없기 때문에,
전체 객체를 대상으로 한 번씩 반복해서 가져오는 반복자를 제공한다.
아래와 같이 호출할 수 있다.
Set<String> set = new HashSet<>();
Iterator<String> iterator = set.iterator();
String 객체를 반복해서 하나씩 가져오는 코드 예시
Set<String> set = new HashSet<>();
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
String str = iterator.next();
}
Iterator의 next() 메소드로 가져온 객체를 제거하고 싶을 때 코드 예시
while (iterator.hasNext()){
String str = iterator.next();
if (str.equals("전원우")){
iterator.remove();
}
}
Iterator 메소드이지만 실제 Set 컬렉션에서 객체가 제거 됨.
B. HashSet
Set 인터페이스의 구현 클래스이다.
선언 방법 :
Set<String> set = new HashSet<>();
HashSet은 중복 객체는 저장하지 않는데,
중복인지 아닌지 판단하는 과정으로
hashCode() 메소드를 호출해서 해시코드를 얻어내고 비교한다. ( hashCode : 해시 알고리즘에 의해 생성된 정수 값 )
동일하다면 다시 equals() 메소드로 비교한 뒤 true가 나오면 동일한 객체로 판단하고 저장하지 않는다.
| Map 컬렉션
키(key)와 값(value)으로 구성된 Map.Entry 객체를 저장하는 구조를 가지고 있다.(Entry는 Map 인터페이스 내부에 선언된 중첩 인터페이스)키와 값은 모두 객체이다.
1. 키(Key)와 값(Value)으로 구성
2. 키는 중복 저장 X
3. 값은 중복 저장 O
A. 메소드 종류
put(K key, V value) | 주어진 키로 값을 저장. 새로운 키 -> null 리턴. 동일한 키 -> 값 대체하고 이전 값 리턴 |
containsKey(object key) | 해당 키가 있는지 확인 |
containsValue(object value) | 해당 값이 있는지 확인 |
Set<Map.Entry<K,V>> entrySet() | 키와 값의 쌍으로 구성된 모든 Map.Entry 객체를 Set에 담아 리턴 |
get(object key) | 해당 키가 있는 값을 리턴 |
size() | 저장된 키의 총 수 리턴 (=길이) |
Collection<V> values() | 저장된 모든 값을 Collection에 담아 리턴 |
clear() | 모든 Map.Entry(키,값)을 삭제 |
remove(object key) | 주어진 키와 일치하는 Map.Entry(키,값)을 삭제 후 값 리턴 |
HashMap 으로 선언했다고 했을 때 대표적인 메소드 예시.
Map<String, Integer> map = new HashMap<>(); // Map<키 타입, 값 타입>
map.put("전원우", 28);
int age = map.get("전원우");
map.remove("전원우");
저장된 전체 객체를 대상으로 하나씩 얻고 싶을 경우 방법 1
Map<String, Integer> map = new HashMap<>();
Set<String> KeySet = map.keySet();
Iterator<String> keyIterator = KeySet.iterator();
while (keyIterator.hasNext()){
String key = keyIterator.next();
int value = map.get(key);
}
KeySet() 메소드로 모든 키를 Set 컬렉션으로 얻은 다음 반복자를 통해 키를 하나씩 얻고 get() 메소드를 통해 값을 얻는다.
저장된 전체 객체를 대상으로 하나씩 얻고 싶을 경우 방법 2
Map<String, Integer> map = new HashMap<>();
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
Iterator<Map.Entry<String, Integer>> entryIterator = entrySet.iterator();
while (entryIterator.hasNext()){
Map.Entry<String, Integer> entry = entryIterator.next();
String key = entry.getKey();
Integer value = entry.getValue();
}
entrySet() 메소드로 모든 Map.Entry를 Set 컬렉션으로 얻은 다음,
반복자를 통해 Map.Entry를 하나씩 얻고 getKey()와 getValue() 메소드를 이용해 키와 값을 얻는다.
B. HashMap
Map 인터페이스를 구현한 대표적인 Map 컬렉션이다.
HashMap의 키로 사용할 객체는 hashCode() 와 equals() 메소드를 재정의해서 동등 객체가 될 조건을 정해야 한다.
객체가 달라도 동등 객체라면 같은 키로 중복 저장되지 않도록 하기 위함이다.
선언 방법 :
Map<String, Integer> map = new HashMap<>();
// Map <키, 값>
키와 값의 타입은 기본타입(byte, short, int, float, dluble, boolean, char)을 사용할 수 없고,
클래스 및 인터페이스 타입만 사용가능하다.
*** 참고 ***
'CS공부' 카테고리의 다른 글
[JAVA] 스택(Stack) 클래스 및 메서드 총정리 (0) | 2023.06.10 |
---|---|
[알고리즘/JAVA] 에라토스테네스의 체 (0) | 2023.05.12 |
[JAVA] 얕은복사(Shallow Copy)와 깊은복사(Deep Copy) (0) | 2023.04.24 |
[알고리즘] 브루트 포스(Brute Force) (0) | 2023.04.06 |
valueOf() 와 parseInt() 차이 (0) | 2023.03.29 |