Preface
이번 장에선 컬렉션 프레임워크에 포함된 다양한 자료구조를 공부했다.
백준에서 자바 문제를 풀어본 후 다른 사람들의 코드를 리뷰할 때 List와 Map 등의 자료구조를 사용한 코드를 자주 볼 수 있었는데, 나는 사용 방법을 모르다보니 지금껏 기본적인 배열만을 사용하여 직접 메소드를 만들어 문제를 해결했었다.
단순히 배열을 사용하는 것보다 컬렉션프레임워크의 클래스나 인터페이스에서 제공하는 다양한 메소드를 이용하면 원하는 결과를 보다 쉽게 얻을 수 있을 것 같다.
1. 컬렉션 프레임워크 소개
- 컬렉션 프레임워크(Collection Framework): 자료구조를 바탕으로 객체들을 효율적으로 관리할 수 있는 인터페이스와 클래스들을 모아둔 것
인터페이스 분류 | 특징 | 구현 클래스 | |
Collection | List | - 순서를 유지하고 저장 - 중복 저장 가능 |
ArrayList, Vector, LinkedList |
Set | - 순서를 유지하지 않고 저정 - 중복 저장 불가 |
HashSet, TreeSet | |
Map | - 키와 값의 쌍으로 저장 - 키는 중복 저장 불가 |
HashMap, Hashtable, TreeMap,Properties |
2. List 컬렉션
- List 컬렉션
1) 객체를 저장하면 자동으로 인덱스를 부여한다.
2) 객체 자체를 저장하는 것이 아닌, 객체의 번지를 참조한다.
3) 동일한 객체 중복 저장이 가능하다. (동일한 번지 참조)
4) null을 저장할 수 있다.
- List 인터페이스의 메소드
기능 | 메소드 | 설명 |
객체 추가 | boolean add(E e) | 주어진 객체를 맨 끝에 추가 |
void add(int index, E element) | 주어진 인덱스에 객체를 추가 | |
E set(int index, E element) | 주어진 인덱스에 저장된 객체를 주어진 객체로 바꿈 | |
객체 검색 | boolean contains(Object o) | 주어진 객체가 저장되어 있는지 여부 |
E get(int index) | 주어진 인덱스에 저장된 객체를 리턴 | |
boolean inEmpty( ) | 컬렉션이 비어 있는지 조사 | |
int size( ) | 저장되어 있는 전체 객체 수를 리턴 | |
객체 삭제 | void clear( ) | 저장된 모든 객체를 삭제 |
E remove(int index) | 주어진 인덱스에 저장된 객체를 삭제 | |
boolean remove(Object o) | 주어진 객체를 삭제 |
- ArrayList
1) 객체를 추가하면 객체가 인덱스로 관리된다.
2) 저장 용량을 초과한 객체가 들어오면 자동으로 저장 용량이 늘어난다.
→ 기본값으로 10개의 객체를 저장할 수 있으며, 원하는 용량이 있다면 생성자의 매개값으로 용량의 크기를 받으면 된다.
3) 특정 인덱스의 객체를 제거하면 바로 뒤 인덱스부터 마지막 인덱스까지 모두 앞으로 1씩 당겨진다.
4) 특정 인덱스에 객체를 삽입하면 해당 인덱스부터 마지막 인덱스까지 모두 1씩 밀려난다.
List<T> list = new ArrayList<T>();
package ch15;
import java.util.ArrayList;
import java.util.List;
public class ArrayListExmaple {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
int size = list.size();
System.out.println("total amount of Entity: " + size);
System.out.println();
String skill = list.get(2); // index num2
System.out.println("2: " + skill);
System.out.println();
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
System.out.println(i + ": " + str);
}
System.out.println();
list.remove(2); // remove index num 2
list.remove(2); // 삭제하면 하나씩 인덱스가 당겨짐
list.remove("E");
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
System.out.println(i + ": " + str);
}
}
}
- Arrays.asList(T...a) 메소드: 고정된 객체들로 구성된 List를 생성
List<T> list = Arrays.asList(T...a);
→ T 타입 파라미터에 맞게 매개값을 순차적으로 입력하거나, T[ ] 배열을 매개값으로 주면 된다.
package ch15;
import java.util.Arrays;
import java.util.List;
public class ArrayAsListExample {
public static void main(String[] args) {
List<String> list1 = Arrays.asList("Kim", "Park", "Lee");
for (String name : list1) {
System.out.println(name);
}
List<Integer> list2 = Arrays.asList(1, 2, 3);
for (int value : list2) {
System.out.println(value);
}
}
}
- Vector
1) ArrayList와 동일한 내부 구조를 지닌다.
2) 동기화된(syncronized) 메소드로 구성되어 있어 멀티 스레드 환경에 안전하다.
List<E> list = new Vector<E>();
- LinkedList
1) 인접 참조를 링크해서 체인처럼 관리한다.
2) 특정 인덱스의 객체를 제거하면 앞뒤 링크만 변경되고 나머지 링크는 변경되지 않는다.
→ 객체를 삽입할 때도 동일하다.
3) LinkedList가 처음 생성될 땐 링크가 만들어지지 않으므로 내부가 비어 있는 상태이다.
List<E> list = new LinkedList<E>();
- ArrayList와 LinkedList의 비교
구분 | 순차적으로 추가/삭제 | 중간에 추가/삭제 | 검색 |
ArrayList | 빠르다 | 느리다 | 빠르다: 읽기 전용에 적합 |
LinkedList | 느리다 | 빠르다: 데이터 변경이 빈번한 경우에 적합 | 느리다 |
3. Set 컬렉션
- Set 컬렉션
1) 저장 순서가 유지되지 않는다.
2) 객체를 중복 저장할 수 없다.
3) 하나의 null만 저장할 수 있다.
4) 인덱스로 관리하지 않는다.
- Set 인터페이스의 메소드
기능 | 메소드 | 설명 |
객체 추가 | boolean add(E e) | 주어진 객체를 저장. 객체가 성공적으로 저장되면 true를, 중복 객체면 false를 리턴 |
객체 검색 | boolean contains(Object o) | 주어진 객체가 저장되어 있는지 여부 |
boolean isEmpty( ) | 컬렉션이 비어 있는지 조사 | |
Iterator<E> iterator( ) | 저장된 객체를 한 번씩 가져오는 반복자 리턴 | |
int size( ) | 저장되어 있는 전체 객체 수 리턴 | |
객체 삭제 | void clear( ) | 저장된 모든 객체를 삭제 |
boolean remove(Object o) | 주어진 객체를 삭제 |
- 반복자: Iterator 인터페이스를 구현한 객체
Set<String> set = ...;
Iterator<String> iterator = set.iterator();
- Iterator 인터페이스의 메소드
리턴 타입 | 메소드명 | 설명 |
boolean | hasNext( ) | 가져올 객체가 있으면 true를, 없으면 false를 리턴한다, |
E | next( ) | 컬렉션에서 하나의 객체를 가져온다. |
void | remove( ) | Set 컬렉션에서 객체를 제거한다. |
- HashSet
1) 객체들을 순서 없이 저장하고 동일한 객체는 중복 저장하지 않는다.
2) 동일한 객체란 꼭 같은 인스턴스를 뜻하는 것이 아니다.
→ haschCode( ) 메소드와 equals( ) 메소드를 통해 비교했을 때 true가 나오면 동일한 객체로 판단하고 중복 저장을 하지 않는다.
Set<E> set = new HashSet<E>();
package ch15;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetExample {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("A");
set.add("B");
set.add("C");
set.add("A"); // A는 한 번만 저장됨
set.add("D");
int size = set.size();
System.out.println("total amounts of Entity: " + size);
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println("\t" + element);
}
set.remove("B");
set.remove("D");
System.out.println("total amounts of Entity: " + size);
iterator = set.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println("\t" + element);
}
set.clear();
if (set.isEmpty()) {
System.out.println("It's empty");
}
}
}
4. Map 컬렉션
- Map 컬렉션
1) 키(key)와 값(value)으로 구성된 Entry 객체를 저장한다.
2) 키와 값은 모두 객체이다.
3) 키는 중복 저장될 수 없지만, 값은 중복 저장될 수 있다.
4) 기존에 저장된 키와 동일한 키를 저장하면 기존 값이 새로운 값으로 대치된다.
- Map 인터페이스의 메소드
기능 | 메소드 | 설명 |
객체 추가 | V put(K key, V value) | 주어진 키로 값을 저장. 새로운 키일 경우 null을 리턴하고 동일한 키가 있을 경우 값을 대체하고 이전 값을 리턴 |
객체 검색 | boolean containsKey(Object key) | 주어진 키가 있는지 여부 |
boolean containsValue(Object value) | 주어진 값이 있는지 여부 | |
Set<Map.Entry<K,V>> entrySet( ) | 키와 값의 쌍으로 구성된 모든 Map.Entry 객체를 Set에 담아서 리턴 | |
V get(Object key) | 주어진 키가 있는 값을 리턴 | |
boolean isEmpty( ) | 컬렉션이 비어 있는지 여부 | |
Set<K> keySet( ) | 모든 키를 Set 객체에 담아서 리턴 | |
int size( ) | 저장된 키의 총 수를 리턴 | |
Collection<V> values( ) | 저장된 모든 값을 Collection에 담아서 리턴 | |
객체 삭제 | void clear( ) | 모든 Map.Entry(키와 값)를 삭제 |
V remove(Object key) | 주어진 키와 일치하는 Map.Entry를 삭제하고 값을 리턴 |
- 저장된 전체 객체를 대상으로 하나씩 얻는 방법
1) keySet( ) 메소드로 모든 키를 Set 컬렉션으로 얻은 후 반복자를 통해 키를 하나씩 얻고 get( ) 메소드를 통해 값을 얻는다.
2) entrySet( ) 메소드로 모든 Map.Entry를 Set 컬렉션으로 얻은 후 반복자를 통해 Map.Entry를 하나씩 얻고 getKey( )와 getValue( ) 메소드를 이용해 키와 값을 얻는다.
- HashMap
1) 키로 사용할 객체는 hashCode( )와 equals( ) 메소드를 재정의해서 동등 객체가 될 조건을 정해야 한다.
→ haschCode( )의 리턴값이 같아야 하고, equals( ) 메소드가 true를 리턴해야 한다.
2) 키와 값의 타입은 기본 타입(byte, short, int, float, double, boolean, char)을 사용할 수 없다.
→ 클래스 및 인터페이스 타입만 사용할 수 있다.
Map<K, V> map = new HashMap<K, V>();
package ch15;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapExample1 {
public static void main(String[] args) {
// Map컬렉션 생성
Map<String, Integer> map = new HashMap<String, Integer>();
// 객체 저장
map.put("Kim", 85);
map.put("Park", 90);
map.put("Lee", 80);
map.put("Cha", 95);
System.out.println("total amounts of Entry: " + map.size());
// 객체 찾기
System.out.println("\tPark: " + map.get("Park"));
System.out.println();
// 객체를 하나씩 처리
Set<String> keySet = map.keySet();
Iterator<String> keyIterator = keySet.iterator();
while (keyIterator.hasNext()) {
String key = keyIterator.next();
Integer value = map.get(key);
System.out.println("\t" + key + ": " + value);
}
System.out.println();
// 객체 삭제
map.remove("Park");
System.out.println("total amounts of Entry: " + map.size());
// 객체를 하나씩 처리
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();
System.out.println("\t" + key + ": " + value);
}
System.out.println();
// 객체 전체 삭제
map.clear();
System.out.println("total amounts of Entry: " + map.size());
}
}
- Hashtable
1) HashMap과 동일한 내부 구조를 지닌다.
2) 동기화된 메소드로 구성되어 있다.
Map<K, V> map = new Hashtable<K, V>();
- Properties
1) Hashtable의 하위 클래스이므로 Hashtable의 모든 특징을 그대로 지닌다.
2) 키와 값이 String 타입으로 제한되어 있다.
3) 프로퍼티 파일을 읽을 때 주로 사용한다.
- 프로퍼티 파일(~.properties): 키와 값이 "=" 기호로 연결되어 있는 텍스트 파일로 ISO 8859-1 문자셋으로 저장된다.
→ 파일을 읽을 땐 Properties 객체를 생성한 후 load(FileReader객체) 메소드를 호출하면 된다.
Properties properties = new Properties();
properties.load(new FileReader("프로퍼티 파일 경로"));
5. 검색 기능을 강화시킨 컬렉션
- 이진 트리(binary tree): 여러 개의 노드가 트리 형태로 연결된 구조
1) 각 노드에 최대 2개의 노드를 연결할 수 있다.
2) 부모 노드의 값보다 작은 노드는 왼쪽에, 큰 값은 오른쪽에 위치시킨다.
→ 왼쪽 마지막 노드: 최소값 / 오른쪽 마지막 노드: 최대값
3) 첫 번째로 저장되는 값은 루트 노드(최상위 노드)가 된다.
4) 문자를 저장하는 경우엔 유니코드 값으로 비교한다.
5) 오름차순 정렬: 왼쪽 노드 → 부모 노드 → 오른쪽 노드
6) 내림차순 정렬: 오른쪽 노드 → 부모 노드 → 왼쪽 노드
- TreeSet
1) 이진트리를 기반으로한 Set 컬렉션
2) 하나의 노드: value(노드값) + 왼쪽과 오른쪽 자식 노드를 참조하기 위한 두 개의 변수
3) TreeSet에 객체를 저장하면 자동으로 정렬된다.
TreeSet<E> treeSet = new TreeSet<E>();
- TreeSet의 검색 메소드
리턴 타입 | 메소드 | 설명 |
E | first( ) | 제일 낮은 객체를 리턴 |
E | last( ) | 제일 높은 객체를 리턴 |
E | lower(E e) | 주어진 객체보다 바로 아래 객체를 리턴 |
E | higher(E e) | 주어진 객체보다 바로 위 객체를 리턴 |
E | floor(E e) | 주어진 객체와 동등한 객체가 있으면 리턴, 만약 없다면 주어진 객체의 바로 아래의 객체를 리턴 |
E | ceiling(E e) | 주어진 객체와 동등한 객체가 있으면 리턴, 만약 없다면 주어진 객체의 바로 위의 객체를 리턴 |
E | pollFirst( ) | 제일 낮은 객체를 꺼내오고 컬렉션에서 제거함 |
E | pollLast( ) | 제일 높은 객체를 꺼내오고 컬렉션에서 제거함 |
package ch15;
import java.util.TreeSet;
public class TreeSetExample {
public static void main(String[] args) {
TreeSet<Integer> scores = new TreeSet<Integer>();
scores.add(87);
scores.add(98);
scores.add(75);
scores.add(95);
scores.add(80);
Integer score = null;
score = scores.first();
System.out.println("The lowest score: " + score);
score = scores.last();
System.out.println("The highst score: " + score + "\n");
score = scores.lower(95);
System.out.println("95점 아래 점수: " + score);
score = scores.higher(95);
System.out.println("95점 위의 점수: " + score + "\n");
score = scores.floor(95);
System.out.println("95점이거나 바로 아래 점수: " + score);
score = scores.ceiling(85);
System.out.println("85점이거나 바로 위의 점수: " + score);
while (!scores.isEmpty()) {
score = scores.pollFirst();
System.out.println("남은 객체 수: " + scores.size());
}
}
}
- TreeSet의 정렬 메소드
리턴 타입 | 메소드 | 설명 |
Iterator<E> | descendingIterator( ) | 내림차순으로 정렬된 Iterator를 리턴 |
NavigableSet<E> | descendingSet( ) | 내림차순으로 정렬된 NavigableSet을 반환 |
- NavigableSet
1) first( ), last( ), lower( ), higher( ), floor( ), ceiling( ) 메소드를 제공한다.
2) 정렬 순서를 바꾸는 descendingSet( ) 메소드를 제공한다.
3) 오름차순으로 정렬하려면 descendingSet( ) 메소드를 두 번 호출하면 된다.
package ch15;
import java.util.NavigableSet;
import java.util.TreeSet;
public class TreeSetExample2 {
public static void main(String[] args) {
TreeSet<Integer> scores = new TreeSet<Integer>();
scores.add(87);
scores.add(98);
scores.add(75);
scores.add(95);
scores.add(80);
NavigableSet<Integer> descendingSet = scores.descendingSet();
for (Integer score : descendingSet) {
System.out.print(score + " ");
}
System.out.println();
NavigableSet<Integer> ascendingSet = descendingSet.descendingSet();
for (Integer score : ascendingSet) {
System.out.print(score + " ");
}
}
}
- TreeSet의 범위 검색 메소드
리턴 타입 | 메소드 | 설명 |
NavigableSet<E> | headSet( E toElement, boolean inclusive ) |
주어진 객체보다 낮은 객체들을 NavigableSet으로 리턴, 주어진 객체 포함 여부는 두 번째 매개값에 따라 달라짐 |
NavigableSet<E> | tailSet( E fromElement, boolean inclusive ) |
주어진 객체보다 높은 객체들을 NavigableSet으로 리턴, 주어진 객체 포함 여부는 두 번째 매개값에 따라 달라짐 |
NavigableSet<E> | subSet( E fromElement, boolean fromInclusive, E toElement, boolean toInclusive ) |
시작과 끝으로 주어진 객체 사이의 객체들을 NavigableSet으로 리턴, 시작과 끝 객체의 포함 여부는 두 번째, 네 번째 매개값에 따라 달라짐 |
package ch15;
import java.util.NavigableSet;
import java.util.TreeSet;
public class TreeSetExample3 {
public static void main(String[] args) {
TreeSet<String> treeSet = new TreeSet<String>();
treeSet.add("apple");
treeSet.add("forever");
treeSet.add("description");
treeSet.add("ever");
treeSet.add("zoo");
treeSet.add("base");
treeSet.add("guess");
treeSet.add("cherry");
System.out.println("c~f 사이의 단어 검색");
NavigableSet<String> rangeSet = treeSet.subSet("c", true, "f", true);
for (String word : rangeSet) {
System.out.println(word);
}
}
}
- TreeMap
1) 이진 트리를 기반으로 한 Map 컬렉션
2) 키와 값이 저장된 Map.Entry를 저장한다.
3) 객체를 저장하면 자동으로 정렬된다. (키 값을 비교)
TreeMap<K, V> treeMap = new TreeMap<K, V>();
- TreeMap의 검색 메소드: TreeSet의 검색 메소드명에 Entry를 추가한 형태로, 기능은 TreeSet의 메소드와 동일하다.
→ 단 리턴 타입이 Map.Entry<K, V>이다.
ex) first( ) → firstEntry( )
ex) PollFirst( ) → PollFirstEntry( )
package ch15;
import java.util.Map;
import java.util.TreeMap;
public class TreeMapExample {
public static void main(String[] args) {
TreeMap<Integer, String> scores = new TreeMap<Integer, String>();
scores.put(87, "Kim");
scores.put(98, "Park");
scores.put(75, "Lee");
scores.put(95, "Cha");
scores.put(80, "Song");
Map.Entry<Integer, String> entry = null;
entry = scores.firstEntry();
System.out.println("가장 낮은 점수: " + entry.getKey() + "-" + entry.getValue());
entry = scores.lastEntry();
System.out.println("가장 높은 점수: " + entry.getKey() + "-" + entry.getValue());
while (!scores.isEmpty()) {
entry = scores.pollFirstEntry();
System.out.println(entry.getKey() + "-" + entry.getValue() + "남은 객체 수: " + scores.size());
}
}
}
- TreeMap의 정렬 메소드 및 범위 검색 메소드
리턴 타입 | 메소드 | 설명 |
NavigableSet<K> | descendingKeySet( ) | |
NavigableMap<K, V> | descendingMap( ) | |
NavigableMap<K, V> | headMap( K toKey, boolean inclusive ) |
|
NavigableMap<K, V> | tailMap( K fromKey, boolean inclusive ) |
|
NavigableMap<K, V> | subMap( K fromKey, boolean fromInclusive, K toKey, boolean, toInclusive ) |
- TreeSet과 TreeMap은 정렬을 위해 java.lang.Comparable을 구현한 객체를 요구한다.
1) 구현하지 않으면 ClassCastException이 발생한다.
2) TreeSet 또는 TreeMap 생성자의 매개값으로 정렬자(Comparator)를 제공하면 Comparable 비구현 객체도 정렬시킬 수 있다.
→ 정렬자: Comparator 인터페이스를 구현한 객체
TreeSet<E> treeSet = new TreeSet<E>(new AscendingComparator());
- 사용자 정의 클래스도 Comparable을 구현하면 자동 정렬이 가능하다.
→ compareTo( ) 메소드를 오버라이딩하여 작으면 음수, 같으면 0, 크면 양수를 리턴하게 하면 된다.
package ch15;
import java.util.Iterator;
import java.util.TreeSet;
class Person implements Comparable<Person> {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person o) {
if (age < o.age) {
return -1;
} else if (age == o.age) {
return 0;
} else {
return 1;
}
}
}
public class ComparableExample {
public static void main(String[] args) {
TreeSet<Person> treeSet = new TreeSet<Person>();
treeSet.add(new Person("Kim", 45));
treeSet.add(new Person("Park", 25));
treeSet.add(new Person("Lee", 31));
Iterator<Person> iterator = treeSet.iterator();
while (iterator.hasNext()) {
Person person = iterator.next();
System.out.println(person.name + ": " + person.age);
}
}
}
6. LIFO와 FIFO 컬렉션
- LIFO: 후입선출
→ Stack 클래스로 구현
- FIFO: 선입선출
→ Queue 인터페이스로 구현
- Stack 클래스의 메소드
Stack<E> stack = new Stack<E>();
리턴 타입 | 메소드 | 설명 |
E | puch(E item) | 주어진 객체를 스택에 넣는다. |
E | peek( ) | 스택의 맨 위의 객체를 가져온다. 객체를 스택에서 제거하지 않는다. |
E | pop( ) | 스택의 맨 위 객체를 가져온다. 객체를 스택에서 제거한다. |
package ch15;
import java.util.Stack;
class Coin {
private int value;
public Coin(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
public class StackExample {
public static void main(String[] args) {
Stack<Coin> coinBox = new Stack<Coin>();
coinBox.push(new Coin(100));
coinBox.push(new Coin(50));
coinBox.push(new Coin(500));
coinBox.push(new Coin(10));
while (!coinBox.isEmpty()) {
Coin coin = coinBox.pop();
System.out.println("꺼내온 동전: " + coin.getValue() + "원");
}
}
}
- Queue 인터페이스의 메소드
→ Queue 인터페이스를 구현한 대표적인 클래스는 LinkedList이다.
Queue<E> queue = new LinkedList<E>();
리턴 타입 | 메소드 | 설명 |
boolean | offer(E e) | 주어진 객체를 넣는다. |
E | peek( ) | 객체 하나를 가져온다. 객체를 큐에서 제거하지 않는다. |
E | poll( ) | 객체 하나를 가져온다. 객체를 큐에서 제거한다. |
package ch15;
import java.util.*;
import java.util.LinkedList;
import java.util.Queue;
class Message {
public String command;
public String to;
public Message(String command, String to) {
this.command = command;
this.to = to;
}
}
public class QueueExample {
public static void main(String[] args) {
Queue<Message> messageQueue = new LinkedList<Message>();
messageQueue.offer(new Message("sendMail", "Kim"));
messageQueue.offer(new Message("sendSMS", "Park"));
messageQueue.offer(new Message("sendDM", "Lee"));
while (!messageQueue.isEmpty()) {
Message message = messageQueue.poll();
switch (message.command) {
case "sendMail":
System.out.println("send mail to " + message.to);
break;
case "sendSMS":
System.out.println("send SMS to " + message.to);
break;
case "sendDM":
System.out.println("send DM to " + message.to);
break;
}
}
}
}
7. 동기화된 컬렉션
- Collections의 syncronizedXXX( ) 메소드: 비동기화된 메소드를 동기화된 메소드로 래핑한다.
→ 매개값으로 비동기화된 컬렉션을 대입하면 동기화된 컬렉션을 리턴한다.
리턴 타입 | 메소드 | 설명 |
List<T> | syncronizedList(List<T> list) | List를 동기화된 List로 리턴 |
Map<K,V> | syncronizedMap<Map<K,V> m) | Map을 동기화된 Map으로 리턴 |
Set<T> | syncronizedSet<Set<T> s) | Set을 동기화된 Set으로 리턴 |
List<T> list = Collections.syncronizedList(new ArrayList<T>());
Set<E> set = Collections.syncronizedSet(new HashSet<E>());
Map<K, V> map = Collections.syncronizedMap(new HashMap<K, V>());
8. 병렬 처리를 위한 컬렉션
- 잠금
1) 전체 잠금: 1개를 처리할 동안 전체 10개의 요소를 다른 스레드가 처리하지 못하도록 하는 것
2) 부분 잠금: 처리하는 요소가 포함된 부분만 잠금하고 나머지 부분은 다른 스레드가 변경할 수 있도록 하는 것
- ConcurrentHashMap: 스레드에 안전하면서 멀티 스레드가 요소를 병렬적으로 처리하기 위해 사용
Map<K,V> map = new ConcurrentHashMap<K,V>();
- ConcurrentLinkedQueue: 락-프리 알고리즘을 구현한 컬렉션
→ 락-프리 알고리즘: 여러 개의 스레드가 동시에 접근할 경우, 잠금을 사용하지 않고도 최소한 하나의 스레드가 안전하게 요소를 저장하거나 얻게 해준다.
Queue<E> queue = new ConcurrentLinkedQueue<E>();
'Java > 이것이 자바다' 카테고리의 다른 글
스트림과 병렬 처리 (0) | 2023.05.07 |
---|---|
이자바 15장(컬렉션 프레임워크) 확인문제 (0) | 2023.05.02 |
이자바 14장(람다식) 확인문제 (0) | 2023.04.28 |
람다식 (0) | 2023.04.27 |
이자바 13장(제네릭) 확인문제 (0) | 2023.04.26 |
댓글