๐ฃ chap8. ์ปฌ๋ ์ API ๊ฐ์
8.1 ์ปฌ๋ ์ ํฉํ ๋ฆฌ
A, B, C๋ฅผ ํฌํจํ๋ ๋ฆฌ์คํธ๋ฅผ ๋ง๋ ๋ค.
1
2
3
4
List<String> friends = new ArrayList<>();
friends.add("A");
friends.add("B");
friends.add("C");
1
List<String> friends = Arrays.asList("A", "B", "C");
UnsupportedOperationException ์์ธ ๋ฐ์
1
friends.add("D");
๊ณ ์ ํฌ๊ธฐ ๋ฐฐ์ด๋ก ๋ง๋ค์ด์ง
Set ๋ง๋ค๊ธฐ
1
2
3
Set<String> friends = new HashSet<>(
Arrays.asList("A", "B", "C")
);
ํน์ stream API๋ฅผ ์ฌ์ฉํ๋ค.
1
2
Set<String> friends = Stream.of("A", "B", "C")
.collect(Collectors.toSet());
๋ ๋ฐฉ๋ฒ ๋ชจ๋ ๋ถํ์ํ ๋จ๊ณ ํ๋์ฉ์ ๊ฑด๋์ผ ํ๊ณ , ๋งค๋๋ฝ์ง ๋ชปํ๊ณ ๋ด๋ถ์ ์ผ๋ก ๋ถํ์ํ ๊ฐ์ฒด ํ ๋น์ ํ์๋ก ํ๋ค.
์๋ฐ9์์ ๋ฆฌ์คํธ, ์งํฉ, ๋งต์ ์ฝ๊ฒ ๋ง๋ค ์ ์๋ย ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ์ง์ํจ
8.1.1 ๋ฆฌ์คํธ ํฉํ ๋ฆฌ
List.of
1
2
List<String> friends = List.of("A", "B", "C");
System.out.println(friends);
- add๋ฅผ ํ๋ฉด ์๋ฌ ๋ฐ์
- ์ ๋ฆฌ์คํธ๋ ๋ถ๋ณ ๋ฆฌ์คํธ
- set() X
- null ์์๋ ๋ถ๊ฐ
์ค๋ฒ๋ก๋ฉ
1
2
3
static <E> List<E> of(E e1, E e2, E e3);
static <E> List<E> of(E e1, E e2, E e3, E e4);
static <E> List<E> of(E... elements);
์ต์ ํ๋ฅผ ์ํ ์ค๋ฒ๋ก๋ฉ
8.1.2 ์งํฉ ํฉํ ๋ฆฌ
1
2
3
Set<String> friends = Set.of("A", "B", "C");
System.out.println(friends);
of ๋ฅผ ํตํด ์ ๊ณตํ ์์ ์ค ์ค๋ณต์ด ์์ผ๋ฉด IllegalArgumentException ๋ฆฌํด
8.1.3 ๋งต ํฉํ ๋ฆฌ
1
2
Map<String, Integer> ageOfFriends =
Map.of("A", 1, "B", 2, "C", 3);
10๊ฐ ์ดํ์ ํค์ ๊ฐ ์์ ๊ฐ์ง ์์ ๋งต ์ ์ฉ
10๊ฐ ์ด์์ ๋งต์ Map.Entry<K, V> ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ๋ฐ๋ ๊ฐ๋ณ ์ธ์๋ก ๊ตฌํ๋ Map.ofEntries ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ์ด์ฉ
1
2
3
4
5
6
7
import static java.util.Map.entry;
Map<String, Integer> ageOfFriends = Map.ofEntries(
entry("A", 1),
entry("B", 2),
entry("C", 3)
);
8.2 ๋ฆฌ์คํธ์ ์งํฉ ์ฒ๋ฆฌ
์๋ฐ 8์์๋ List, Set ์ธํฐํ์ด์ค์ ๋ค์๊ณผ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ค.
- removeIf : ํ๋ ๋์ผ์ดํธ๋ฅผ ๋ง์กฑํ๋ ์์๋ฅผ ์ ๊ฑฐํ๋ค.
- replaceAll : UnaryOperator ํจ์๋ฅผ ์ด์ฉํด ์์๋ฅผ ๋ฐ๊พผ๋ค. ๋ฆฌ์คํธ์์ ์ฌ์ฉํ ์ ์๋ค.
- sort : ๋ฆฌ์คํธ๋ฅผ ์ ๋ ฌํ๋ค.
์ด ๋ฉ์๋๋ ์๋ก์ด ๊ฒฐ๊ณผ๋ฅผ ๋ง๋๋ ์คํธ๋ฆผ ๋์๊ณผ ๋ฌ๋ฆฌ ํธ์ถํ ๊ธฐ์กด ์ปฌ๋ ์ ์์ฒด๋ฅผ ๋ฐ๊พผ๋ค.
์ปฌ๋ ์ ์ ๋ฐ๊พธ๋ ๋์์ ์๋ฌ๋ฅผ ์ ๋ฐํ๋ฉฐ ๋ณต์กํจ์ ๋ํ๊ธฐ ๋๋ฌธ์ ์๋ฐ 8์์๋ removeIf์ replaceAll์ ์ถ๊ฐํ๋ค.
8.2.1 removeIf ๋ฉ์๋
๋ค์์ ์ซ์๋ก ์์๋๋ ์ฐธ์กฐ ์ฝ๋๋ฅผ ๊ฐ์ง ํธ๋์ญ์ ์ ์ญ์ ํ๋ ์ฝ๋๋ค.
1
2
3
4
5
for(Transaction transaction : transactions) {
if(Character.isDigit(transaction.getReferenceCode().charAt(0))) {
transaction.remove(transaction);
}
}
์ฝ๋๋ฅผ ์คํํด๋ณด๋ฉด ConcurrentModificationException์ ์ผ์ผํจ๋ค.
forEach ๋ฃจํ๋ Iterator ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ์ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ด ํด์๋๋ค.
1
2
3
4
5
6
7
for(Iterator<Transaction> iterator = transactions.iterator(); iterator.hasNext(); ) {
Transaction transaction = iterator.next();
if(Character.isDigit(transaction.getReferenceCode().charAt(0))) {
transactions.remove(transaction);
// ๋ฐ๋ณต์๋ฅผ ์ฌ์ฉํด ๋ฆฌ์คํธ๋ฅผ ์ํํ๋ฉด์, ๋ฆฌ์คํธ๋ฅผ ์ง์ ์์ ํ๊ณ ์์ -> ๋ฌธ์ ๋ฐ์
}
}
Iterator ๊ฐ์ฒด๋ฅผ ํตํด ์์ค๋ฅผ ์ง์ํ๊ณ , Collection ๊ฐ์ฒด ์์ฒด์ remove()๋ฅผ ํธ์ถํด ์์๋ฅผ ์ญ์ ํ๊ณ ์๋ค.
๋ฐ๋ผ์ ๋ฐ๋ณต์์ ์ํ์ ์ปฌ๋ ์ ์ ์ํ๊ฐ ๋๊ธฐํ๋์ง ์๋๋ค.
Iterator ๊ฐ์ฒด๋ฅผ ๋ช ์์ ์ผ๋ก ์ฌ์ฉํ๊ณ ๊ทธ ๊ฐ์ฒด์ remove() ๋ฉ์๋๋ฅผ ํธ์ถํด์ค์ผ ์ ์์ ์ผ๋ก ๋์ํ๋ค.
1
2
3
4
5
6
for(Iterator<Transaction> iterator = transactions.iterator(); iterator.hasNext(); ) {
Transaction transaction = iterator.next();
if(Character.isDigit(transaction.getReferenceCode().charAt(0))) {
iterator.remove();
}
}
์์ ๋ณต์กํ ์ฝ๋ ํจํด์ ์๋ฐ 8์ removeIf ๋ฉ์๋๋ก ๋ฐ๊ฟ ์ ์๋ค. removeIf๋ ์ญ์ ํ ์์๋ฅผ ๊ฐ๋ฆฌํค๋ ํ๋ ๋์ผ์ดํธ๋ฅผ ์ธ์๋ก ๋ฐ๋๋ค.
1
2
transactions.removeIf(transaction ->
Character.isDigit(transaction.getReferenceCode().charAt(0))); // True์ธ ๊ฒฝ์ฐ ์ ๊ฑฐ
8.2.2 replaceAll ๋ฉ์๋
replaceIf์ฒ๋ผ ์์๋ฅผ ์ ๊ฑฐํ๋ ๊ฒ ์๋๋ผ ๋ฐ๊ฟ์ผ ํ๋ ์ํฉ์ผ ๋, replaceAll์ ์ฌ์ฉํ ์ ์๋ค.
List ์ธํฐํ์ด์ค์ replaceAll ๋ฉ์๋๋ฅผ ์ด์ฉํด ๋ฆฌ์คํธ์ ๊ฐ ์์๋ฅผ ์๋ก์ด ์์๋ก ๋ฐ๊ฟ ์ ์๋ค.
์๋๋ ์คํธ๋ฆผ API๋ฅผ ์ฌ์ฉํ ์์ ์ด๋ค.
1
2
3
4
5
referenceCodes.stream() // [a12, C14, b13]
.map(code -> Character.toUpperCase(code.charAt(0)) + code.subString(1))
// ์คํธ๋ฆผ์ ๊ฐ ์์์ ๋ํด ํจ์๋ฅผ ์ ์ฉํ์ฌ ์๋ก์ด ์คํธ๋ฆผ์ ์์ฑ
.collect(Collectors.toList())
.forEach(System.out::println);
1
2
3
4
5
// ๊ฒฐ๊ณผ
A12
C14
B13
ํ์ง๋ง ์ด ์ฝ๋๋ ์ ๋ฌธ์์ด ์ปฌ๋ ์ ์ ๋ง๋ ๋ค. ๊ธฐ์กด ์ปฌ๋ ์ ์ ๋ฐ๊พธ๋ ค๋ฉด ListIterator ๊ฐ์ฒด๋ฅผ ์ด์ฉํด์ผ ํ๋ค.
1
2
3
4
5
for(ListIterator<String> iterator = referenceCodes.listIterator(); iterator.hasNext(); ) {
String code = iterator.next();
iterator.set(Character.toUpperCase(code.charAt(0)) + code.substring(1));
// ๋ณ๊ฒฝ๋ ๊ฐ์ iterator.set() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํ์ฌ ์์์ ๋์
ํ์ฌ ์์
}
์ฝ๋๊ฐ ๋ณต์กํด์ก๋ค. ๊ทธ๋ฆฌ๊ณ ์ด์ฒ๋ผ ์ปฌ๋ ์ ๊ฐ์ฒด์ Iterator ๊ฐ์ฒด๋ฅผ ํผ์ฉํ๋ฉด ๋ฐ๋ณต๊ณผ ๋ณ๊ฒฝ์ด ๋์์ ์ด๋ฃจ์ด์ ธ ์ฝ๊ฒ ๋ฌธ์ ๋ฅผ ์ผ์ผํจ๋ค.
์๋ฐ 8์ replaceAll ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์๋ค.
1
referenceCodes.replaceAll(code -> Character.toUpperCase(code.charAt(0)) + code.substring(1));
๋ค์ 8.3์ ์์๋ Map ์ธํฐํ์ด์ค์ ์ถ๊ฐ๋ ์ ๊ธฐ๋ฅ์ ์ค๋ช ํ๋ค.
8.3. ๋งต ์ฒ๋ฆฌ
์๋ฐ 8์์๋ Map ์ธํฐํ์ด์ค์ ๋ํดํธ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ค.
8.3.1. forEach ๋ฉ์๋
๋งต์์ ํค์ ๊ฐ์ ๋ฐ๋ณตํ๋ ์์
์ ์ํด ์๋ฐ 8์์๋ถํฐ Map ์ธํฐํ์ด์ค๋ BiConsumer(ํค์ ๊ฐ์ ์ธ์๋ก ๋ฐ์)๋ฅผ ์ธ์๋ก ๋ฐ๋ย forEach
ย ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
1
2
3
4
5
6
7
8
9
// forEach ๋ฉ์๋ ๋ฏธ์ฌ์ฉ
for (Map.Entry<String, Integer> entry : ageOfFriends.entrySet()) {
String friend = entry.getKey();
Integer age = entry.getValue();
System.out.println(friend + " is " + age + " years old");
}
// forEach ๋ฉ์๋ ์ฌ์ฉ
ageOfFriends.forEach((friend, age) -> System.out.println(friend + " is " + age + " years old"));
8.3.2 ์ ๋ ฌ ๋ฉ์๋
Entry.comparingByValue
,ย Entry.comparingByKey
๋ฅผ ์ด์ฉํ๋ฉด ๋งต์ ํญ๋ชฉ์ ๊ฐ ๋๋ ํค๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌํ ์ ์๋ค.
1
2
3
4
5
6
7
8
Map<String, String> favouriteMovies = Map.ofEntries(entry("Raphael", "Star Wars"),
entry("Cristina", "Matrix"),
entry("Olivia", "James Bond"));
favouriteMovies.entrySet()
.stream()
.sorted(Entry.comparingByKey()) // ์ฌ๋์ ์ด๋ฆ์ ์ํ๋ฒณ ์์ผ๋ก ์คํธ๋ฆผ ์์ ์ฒ๋ฆฌ
.forEachOrdered(System.out::println);
HashMap ์ฑ๋ฅ
์๋ฐ 8์์๋ HashMap์ ๋ด๋ถ ๊ตฌ์กฐ๋ฅผ ๋ฐ๊ฟ ์ฑ๋ฅ์ ๊ฐ์ ํ๋ค.
๊ธฐ์กด์ ๋งต์ ํญ๋ชฉ์ ๋ง์ ํค๊ฐ ๊ฐ์ ํด์์ฝ๋๋ฅผ ๋ฐํํ๋ ์ํฉ์ด ๋๋ฉด O(n)์ ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ LinkedList๋ก ๋ฒํท์ ๋ฐํํด์ผ ํ๋ฏ๋ก ์ฑ๋ฅ์ด ์ ํ๋์๋ค.
์ต๊ทผ์๋ ๋ฒํท์ด ๋๋ฌด ์ปค์ง๋ฉด O(log(n))์ ์๊ฐ์ด ์์๋๋ ์ ๋ ฌ๋ ํธ๋ฆฌ๋ฅผ ์ด์ฉํด ๋์ ์ผ๋ก ์นํํด ์ถฉ๋์ด ์ผ์ด๋๋ ์์ ๋ฐํ ์ฑ๋ฅ์ ๊ฐ์ ํ๋ค. (ํค๊ฐ Comparable ํํ์ฌ์ผ ์ ๋ ฌ๋ ํธ๋ฆฌ๋ฅผ ์ง์)
8.3.3 getOrDefault ๋ฉ์๋
ํค๊ฐ ์กด์ฌํ์ง ์์ผ๋ฉด ๊ฒฐ๊ณผ๊ฐ null์ด ๋ฐํ๋๋ฏ๋ก NullPointerException์ ๋ฐฉ์งํ๊ธฐ ์ํด ์์ฒญ ๊ฒฐ๊ณผ์ null ์ฌ๋ถ๋ฅผ ํ์ธํด์ผ ํ๋ค.
๊ธฐ๋ณธ๊ฐ์ ๋ฐํํ๋ย getOrDefault
ย ๋ฉ์๋๋ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ํค๋ฅผ, ๋ ๋ฒ์งธ ์ธ์๋ก ๊ธฐ๋ณธ๊ฐ์ ๋ฐ์ ๋งต์ ํค๊ฐ ์กด์ฌํ์ง ์์ผ๋ฉด ๋ ๋ฒ์งธ ์ธ์๋ก ๋ฐ์ ๊ธฐ๋ณธ๊ฐ์ ๋ฐํํ๋ค.
1
2
3
4
Map<String, String> favouriteMovies = Map.ofEntries(entry("Raphael", "Star Wars"), entry("Olivia", "James Bond"));
System.out.println(favouriteMovies.getOrDefault("Olivia", "Matrix")); // James Bond ์ถ๋ ฅ
System.out.println(favouriteMovies.getOrDefault("Thibaut", "Matrix")); // Matrix ์ถ๋ ฅ
ํค๊ฐ ์กด์ฌํ๋๋ผ๋ ๊ฐ์ด null์ธ ์ํฉ์์๋ย getOrDefault
๊ฐ null์ ๋ฐํํ ์ ์๋ค.
8.3.4 ๊ณ์ฐ ํจํด
ํค ์กด์ฌ ์ฌ๋ถ์ ๋ฐ๋ผ ์ด๋ค ๋์์ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํด์ผํ๋ ์ํฉ์ด ํ์ํ ๋๊ฐ ์๋ค.
๋ค์์ 3๊ฐ์ง ์ฐ์ฐ์ด ์ด๋ฐ ์ํฉ์ ๋์์ด ๋๋ค.
computeIfAbsent
ย : ์ ๊ณต๋ ํค์ ํด๋นํ๋ ๊ฐ์ด ์์ผ๋ฉด(ํน์ null) ํค๋ฅผ ์ด์ฉํด ์ ๊ฐ์ ๊ณ์ฐํ๊ณ ๋งต์ ์ถ๊ฐํ๋ค.computeIfPresent
ย : ์ ๊ณต๋ ํค๊ฐ ์กด์ฌํ๋ฉด ์ ๊ฐ์ ๊ณ์ฐํ๊ณ ๋งต์ ์ถ๊ฐํ๋ค.compute
ย : ์ ๊ณต๋ ํค๋ก ์ ๊ฐ์ ๊ณ์ฐํ๊ณ ๋งต์ ์ ์ฅํ๋ค.- Map์ ์ด์ฉํ ์บ์ ๊ตฌํ
1
2
3
4
5
6
7
8
9
10
11
12
13
// ์บ์
Map<String, byte[]> dataToHash = new HashMap<>();
// ๊ฐ ๋ผ์ธ์ SHA-256์ ํด์ ๊ฐ์ผ๋ก ๊ณ์ฐํด์ ์ ์ฅํ๊ธฐ ์ํ ๊ณ์ฐ ๊ฐ์ฒด
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
// ํค๊ฐ ์๋ค๋ฉด line๊ณผ ๊ณ์ฐ๋ ํด์ ๊ฐ์ด key,value๋ก ๋ค์ด๊ฐ
lines.forEach(line -> dataToHash.computeIfAbsent(line, this::calculateDigest));
// ํค์ ํด์๋ฅผ ๊ณ์ฐํด์ ๋ฐํ
private byte[] calculateDigest(String key) {
return messageDigest.digest(key.getBytes(StandardCharsets.UTF_8));
}
- ํค๊ฐ ์กด์ฌํ์ง ์์ผ๋ฉด ๊ฐ์ ๋ฐํ
์๋ ์ฝ๋๋ ํค๊ฐ ์กด์ฌํ๋ฉด ๊ธฐ์กด ๊ฐ์, ์กด์ฌํ์ง ์์ผ๋ฉด ์๋ก์ด ๋ฆฌ์คํธ์ โStar Warsโ๊ฐ ์ถ๊ฐ ๋๋ค.
1
2
friendsToMovies.computeIfAbsent("Raphael", name -> new ArrayList<>())
.add("Star Wars");
8.3.5 ์ญ์ ํจํด
์๋ฐ 8์์๋ ํค๊ฐ ํน์ ํ ๊ฐ๊ณผ ์ฐ๊ด๋์์ ๋๋ง ํญ๋ชฉ์ ์ ๊ฑฐํ๋ ์ค๋ฒ๋ก๋ ๋ฒ์ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
- ์๋ฐ 8 ์ด์
1
2
3
4
5
6
7
8
String key = "Raphael";
String value = "Jack Reacher 2";
if (favouriteMovies.containsKey(key) && Objects.equals(favouriteMovies.get(key), value)) {
favouriteMovies.remove(key);
return true;
} else {
return false;
}
- ์๋ฐ 8 ์ดํ
1
favouriteMovies.remove(key, value);
8.3.6 ๊ต์ฒด ํจํด
๋งต์ ํญ๋ชฉ์ ๋ฐ๊พธ๋๋ฐ ์ฌ์ฉํ๋ ๋ฉ์๋
replaceAll
ย : BiFunction์ ์ ์ฉํ ๊ฒฐ๊ณผ๋ก ๊ฐ ํญ๋ชฉ์ ๊ฐ์ ๊ต์ฒดํ๋ค.replace
ย : ํค๊ฐ ์กด์ฌํ๋ฉด ๋งต์ ๊ฐ์ ๋ฐ๊พผ๋ค. ํค๊ฐ ํน์ ๊ฐ์ผ๋ก ๋งคํ๋์์ ๋๋ง ๊ฐ์ ๊ต์ฒดํ๋ ์ค๋ฒ๋ก๋ ๋ฒ์ ๋ ์๋ค.
1
2
3
4
5
Map<String, String> favouriteMovies = new HashMap<>();
favouriteMovies.put("Raphael", "Star Wars");
favouriteMovies.put("Olivia", "james bond");
favouriteMovies.replaceAll((friend, movie) -> movie.toUpperCase());
8.3.7 ํฉ์นจ
putAll
ย ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ ๋ ๋งต์ ํฉ์น ์ ์๋ค.
๊ทธ๋ฌ๋ย putAll
์ ์ค๋ณต๋ ํค๊ฐ ์๋ค๋ฉด ์ ๋๋ก ๋์ํ์ง ์๋๋ค.
์ด๋๋ ์ค๋ณต๋ ํค๋ฅผ ์ด๋ป๊ฒ ํฉ์น ์ง ๊ฒฐ์ ํ๋ย BiFunction
์ ์ธ์๋ก ๋ฐ๋ merge
ย ๋ฉ์๋๋ฅผ ์ฌ์ฉ
- putAll ์ฌ์ฉ
1
2
3
4
5
Map<String, String> family = Map.ofEntries(entry("Teo", "Star Wars"), entry("Cristina", "James Bond"));
Map<String, String> friends = Map.ofEntries(entry("Raphael", "Star Wars"));
Map<String, String> everyone = new HashMap<>(family);
everyone.putAll(friends);
- merge ์ฌ์ฉ
์ค๋ณต๋ ํค๊ฐ ์์ผ๋ฉด ๋ ๊ฐ์ ์ฐ๊ฒฐํ๊ณ ์์ผ๋ฉด (key, value) ๊ทธ๋๋ก ์ ์ฅํ๋ค.
1
2
3
Map<String, String> everyone = new HashMap<>(family);
friends.forEach((key, value) -> everyone.merge(key, value, (movie1, movie2) -> movie1 + " & " + movie2));
System.out.println(everyone);
- merge๋ฅผ ์ด์ฉํ ์ด๊ธฐํ ๊ฒ์ฌ
์ํ๋ ๊ฐ์ด ์ด๊ธฐํ๋์ด ์์ผ๋ฉด +1, ์ด๊ธฐํ ๋์ด์์ง ์์ null์ด๋ฉด (movieName, 1) ์ ์ฅํ๋ค.
1
moviesToCount.merge(movieName, 1L, (key, count) -> count + 1L);
8.4 ๊ฐ์ ๋ ConcurrentHashMap
ConcurrentHashMap
- ๋์์ฑ ์นํ์ ์ด๋ฉฐย ์ต์ ๊ธฐ์ ์ ๋ฐ์ํ HashMap ๋ฒ์
- ๋ด๋ถ ์๋ฃ๊ตฌ์กฐ์ย ํน์ ๋ถ๋ถ๋ง ์ ๊ฐย ๋์ ์ถ๊ฐ, ๊ฐฑ์ ์์ ์ ํ์ฉํจ
- ๋๊ธฐํ๋ Hashtable ๋ฒ์ ์ ๋นํดย ์ฝ๊ธฐ/์ฐ๊ธฐ ์ฐ์ฐ ์ฑ๋ฅ์ด ์๋ฑํ๋ค
- (์ฐธ๊ณ ๋ก, ํ์ค HashMap์ ๋น๋๊ธฐ๋ก ๋์ํจ)
1
2
3
4
5
6
7
8
9
10
11
12
13
public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V>, Serializable {
public V get(Object key) {}
public boolean containsKey(Object key) { }
public V put(K key, V value) {
return putVal(key, value, false);
}
...
}
์ฐธ๊ณ : Hashtable Class
1
2
3
4
5
6
7
8
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable {
public synchronized int size() { }
@SuppressWarnings("unchecked")
public synchronized V get(Object key) { }
public synchronized V put(K key, V value) { } }
- ๋ฉ์๋ ์ ์ฒด์ย
synchronized
ย ํค์๋๊ฐ ์กด์ฌ (๋ฉ์๋ ์ ์ฒด๊ฐ ์๊ณ๊ตฌ์ญ์ผ๋ก ์ค์ ๋จ) - ๋ค๋ง, ๋์์ ์์ ์ ํ๋ คํด๋ ๊ฐ์ฒด๋ง๋ค Lock์ ํ๋์ฉ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ ๋์์ ์ฌ๋ฌ ์์ ์ ํด์ผํ ๋ ๋ณ๋ชฉํ์์ด ๋ฐ์ํ ์ ๋ฐ์ ์์
์ฐธ๊ณ : HashMap
1
2
3
4
5
6
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {
public V get(Object key) {}
public V put(K key, V value) {}
}
synchronized
ย ํค์๋๊ฐย ์กด์ฌํ์ง ์์Map
ย ์ธํฐํ์ด์ค๋ฅผย ๊ตฌํํ ํด๋์ค ์ค์์ ์ฑ๋ฅ์ด ์ ์ผ ์ข๋ค๊ณ ํ ์ ์์Multi-Thread
ย ํ๊ฒฝ์์ ์ฌ์ฉํ ์ ์๋ค๋ ํน์ง
8.4.1. ์ฐ์ฐ
forEach
ย : ๊ฐ key-value ์์ ์ฃผ์ด์ง ์ก์ ์ ์ํreduce
ย : ๋ชจ๋ key-value ์์ ์ ๊ณต๋ reduce ํจ์๋ฅผ ์ด์ฉํด ๊ฒฐ๊ณผ๋ก ํฉ์นจsearch
ย : null์ด ์๋ ๊ฐ์ ๋ฐํํ ๋๊น์ง ๊ฐ key-value ์์ ํจ์๋ฅผ ์ ์ฉ
์ฐ์ฐ์ ์ข ๋ฅ
- key-value๋ก ์ฐ์ฐ :ย
forEach
,ยreduce
,ยsearch
- key๋ก ์ฐ์ฐ :ย
forEachKey
,ยreduceKeys
,ยsearchKeys
- value๋ก ์ฐ์ฐ :ย
forEachValue
,ยreduceValues
,ยsearchValues
- Map.Entry๋ก ์ฐ์ฐ :ย
forEachEntry
,ยreduceEntries
,ยsearchEntries
์ฐ์ฐ์ ์ ์์ฌํญ
- ์๋์ ์ฐ์ฐ๋ค์ ConcurrentHashMap์ ์ํ๋ฅผ ์ ๊ทธ์ง ์๊ณ ์ฐ์ฐ์ ์ํ โ ์ฐ์ฐ์ ์ ๊ณตํ ํจ์๋ย ๊ณ์ฐ์ด ์งํ๋๋ ๋์ ๋ฐ๋ ์ ์๋ ๊ฐ์ฒด, ๊ฐ, ์์ ๋ฑ์ ์์กดํ์ง ์์์ผ ํจ
- ๋ณ๋ ฌ์ฑ ๊ธฐ์ค๊ฐ(threshold)๋ฅผ ์ง์ ํด์ผ ํจ
- ๋งต์ ํฌ๊ธฐ๊ฐ ์ฃผ์ด์ง ๊ธฐ์ค๊ฐ๋ณด๋ค ์์ผ๋ฉด ์์ฐจ์ ์ผ๋ก ์ฐ์ฐ์ ์คํํจ
๊ธฐ์ค๊ฐ = 1
ย : ๊ณตํต ์ค๋ ๋ ํ์ ์ด์ฉํด ๋ณ๋ ฌ์ฑ์ ๊ทน๋ํํจ๊ธฐ์ค๊ฐ = Long.MAX_VALUE
ย : ํ ๊ฐ์ ์ค๋ ๋๋ก ์ฐ์ฐ์ ์คํํจ- (SW ์ํคํ
์ฒ๊ฐ ๊ณ ๊ธ ์์ค์ ์ต์ ํ๊ฐ ์๋๋ผ๋ฉด) ๊ธฐ์ค๊ฐ ๊ท์น์ ๋ฐ๋ฅด๋ ๊ฒ์ด ์ข์
1 2 3 4
public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V>, Serializable { private static final int DEFAULT_CAPACITY = 16; // ๋์์ ์ ๋ฐ์ดํธ๋ฅผ ์ํํ๋ ์ฐ๋ ๋ ์ private static final int DEFAULT_CONCURRENCY_LEVEL = 16; }
DEFAULT_CONCURRENCY_LEVEL
ย : ๋์์ ์์ ๊ฐ๋ฅํ ์ฐ๋ ๋ ์DEFAULT_CAPACITY
ย : ๋ฒํท์ ์- ์ฆ,ย ์ฌ๋ฌ ์ฐ๋ ๋์์ ConcurrentHashMap ๊ฐ์ฒด์ ๋์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ , ์ฐธ์กฐํ๋๋ผ๋ ๊ทธ ๋ฐ์ดํฐ๊ฐ ๋ค๋ฅธ ์ธ๊ทธ๋จผํธ์ ์์นํ๋ฉด ์๋ก ๋ฝ์ ์ป๊ธฐ ์ํดย ๊ฒฝ์ํ์ง ์์
์ฐ์ฐ ํ์ฉ ์์
reduceValues
๋ฅผ ํ์ฉํ์ฌ ๋งต์ ์ต๋๊ฐ์ ์ฐพ๋ ์ฝ๋
1
2
3
ConcurrentHashMap<String, Long> map = new ConcurrentHashMap<>();
long parallelismThreshold = 1;
Optional<Integer> maxValue = Optional.ofNullable(map.reduceValues(parallelismThreshold, Long::max));
- int, long, double ๋ฑ์ ๊ธฐ๋ณธ๊ฐ์๋ ์ ์ฉ each reduce ์ฐ์ฐ์ด ์ ๊ณต๋จ โ ์ด๋ฅผ ์ ํ์ฉํ๋ฉด ๋ฐ์ฑ ์์
์ ํ ํ์๊ฐ ์๊ณ , ํจ์จ์ ์ผ๋ก ์์
์ ์ฒ๋ฆฌํ ์ ์์ (ex:ย
reduceValuesToInt
,ยreduceKeysToLong
)
8.4.2. ๊ณ์
ConcurrentHashMapย ํด๋์ค : Map์ ๋งคํ ๊ฐ์๋ฅผ ๋ฐํํ๋ย
mappingCount
ย ๋ฉ์๋๋ฅผ ์ ๊ณตํจ- ํค์ ๊ฐ์ย ๋งคํ์ย ์
๊ธฐ์กด์ size ๋ฉ์๋ ๋์ ์ ์ฝ๋์๋ int๋ฅผ ๋ฐํํ๋ย
mappingCount
ย ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค โ ๋งคํ์ ๊ฐ์๊ฐ int์ ๋ฒ์๋ฅผ ๋์ด์๋ ์ดํ์ ์ํฉ์ ๋์ฒํ ์ ์์
8.4.3. ์งํฉ๋ทฐ
keySet
ย : ์๊ธฐ ์์ ์ ์งํฉ ๋ทฐ๋ก ๋ฐํํ๋ ์ ๋ฉ์๋1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
// Java code to illustrate the keys() method import java.util.*; import java.util.concurrent.*; public class ConcurrentHashMapDemo { public static void main(String[] args) { // Creating an empty ConcurrentHashMap ConcurrentHashMap<Integer, String> hash_map = new ConcurrentHashMap<Integer, String>(); // Mapping string values to int keys hash_map.put(10, "Geeks"); hash_map.put(15, "4"); hash_map.put(20, "Geeks"); hash_map.put(25, "Welcomes"); hash_map.put(30, "You"); // Displaying the HashMap System.out.println("Initial Mappings are: " + hash_map); // Using keySet() to get the set view of keys System.out.println("The set is: " + hash_map.keySet()); } }
1 2 3 4
// output // Initial Mappings are: {20=Geeks, 25=Welcomes, 10=Geeks, 30=You, 15=4} // The set is: [20, 25, 10, 30, 15]
- Map์ ๋ฐ๊พธ๋ฉด ์งํฉ๋ ๋ฐ๋๊ณ , ๋ฐ๋๋ก ์งํฉ์ ๋ฐ๊พธ๋ฉด ๋งต๋ ์ํฅ์ ๋ฐ์
newKeySet
ย : ConcurrentHashMap์ผ๋ก ์ ์ง๋๋ ์งํฉ ๋ง๋ค๊ธฐ1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
importย java.util.Set; importย java.util.concurrent.*; classย ConcurrentHashMapnewKeySetExample1ย { publicย staticย voidย main(String[]ย args) { Set<String>ย hashmapย =ย ConcurrentHashMap.newKeySet(); hashmap.add("AA"); hashmap.add("BBB"); hashmap.add("CCC"); hashmap.add("DDD"); System.out.println("ย Mappingsย :ย "+ย hashmap); } } // output // Mappings : [AA, CCC, BBB, DDD]