π¦ chap9. 리ν©ν°λ§, ν μ€ν , λλ²κΉ
chap8. 컬λ μ API κ°μ
8.1 컬λ μ ν©ν 리
μλ° 9μμλ μμ 컬λ μ κ°μ²΄λ₯Ό μ½κ² λ§λ€ μ μλ λͺ κ°μ§ λ°©λ²μ μ 곡νλ€.
1
2
3
4
List<String> friends = new ArrayList<>();
friends.add("Raphael");
friends.add("Olivia");
friends.add("Thibaut");
μ μ μμλ₯Ό ν¬ν¨νλ 리μ€νΈλ₯Ό ν©ν 리 λ©μλλ‘ κ°λ¨νκ² μ€μΌ μ μλ€.
1
2
List<String> friends
= Arrays.asList("Rapheal", "Olivia", "Thibaut");
μ΄λ κ³ μ ν¬κΈ°μ 리μ€νΈλ‘ μμλ₯Ό μΆκ°νκ±°λ μμ ν μ μλ€.
μμμ κ°±μ μ κ°λ₯νλ€.
UnsupportedOperationException μμΈ λ°μ
λ΄λΆμ μΌλ‘ κ³ μ λ ν¬κΈ°μ λ³νν μ μλ λ°°μ΄λ‘ ꡬνλμκΈ° λλ¬Έμ μμΉ γ λ°μνλ€.
Arrays.asSet()
μ΄λΌλ ν©ν 리 λ©μλλ μμΌλ―λ‘ λ€λ₯Έ λ°©λ²μ΄ νμνλ€.
1
2
3
4
5
6
Set<String> friends
= new HashSet<>(Arrays.asList("Raphael", "Olivia", "Thibaut"));
Set<String> friends
= Stream.of("Raphael", "Olivia", "Thibaut")
.collect(Collectors.toSet());
νμ§λ§ λ λ°©λ² λͺ¨λ 맀λλ½μ§ λͺ»νλ©° λ΄λΆμ μΌλ‘ λΆνμν κ°μ²΄ ν λΉμ΄ νμνλ€.
λν κ²°κ³Όλ λ³νν μ μλ μ§ν©μ΄λΌλ μ¬μ€μ μ£Όλͺ©νμ.
8.1.1 리μ€νΈ ν©ν 리
1
List<String> friends = List.of("Raphael", "Olivia", "Thibaut");
List.of
ν©ν 리 λ©μλλ₯Ό μ΄μ©νμ¬ κ°λ¨νκ² λ¦¬μ€νΈλ₯Ό λ§λ€ μ μλ€.
μ΄ λ¦¬μ€νΈλ λΆλ³λ¦¬μ€νΈλ‘ add
λλ set
λ©μλλ‘ λ¦¬μ€νΈλ₯Ό λ°κΎΈλ € νλ©΄ java.lang.UnsupportedOperationException
μ΄ λ°μνλ€.
λν null μμλ₯Ό κΈμ§νμ¬ μλμΉ μμ λ²κ·Έλ₯Ό λ°©μ§νκ³ μ‘°κΈ λ κ°κ²°ν λ΄λΆ ꡬνμ λ¬μ±νλ€.
List
μΈν°νμ΄μ€μλ List.of
μ λ€μν μ€λ²λ‘λ λ²μ μ΄ μλ€.
μ κ°λ³ μΈμλ‘ λ€μ€ μμλ₯Ό λ°μ μ μλλ‘ νμ§ μμμκΉ?
λ΄λΆμ μΌλ‘ κ°λ³ μΈμ λ²μ μ μΆκ° λ°°μ΄μ ν λΉν΄μ 리μ€νΈλ‘ κ°μΌλ€.
μ¦ λ°°μ΄μ ν λΉνκ³ μ΄κΈ°ννλ©° λμ€μ GCμ λν λΉμ©μ μ§λΆν΄μΌ νλ€.
κ³ μ λ μ«μμ μμλ₯Ό APIλ‘ μ μνλ©΄ μ΄λ° λΉμ©μ μ κ±°ν μ μλ€.
λ°μ΄ν° μ²λ¦¬ νμμ μ€μ νκ±°λ λ°μ΄ν°λ₯Ό λ³νν νμκ° μλ€λ©΄ μ¬μ©νκΈ° κ°νΈν ν©ν 리 λ©μλλ₯Ό μ΄μ©νμ!
8.1.2 μ§ν© ν©ν 리
1
Set<String> friends = Set.of("Raphael", "Olivia", "Thibaut");
μ€λ³΅λ μμλ₯Ό μ κ³΅ν΄ μ§ν©μ λ§λ€λ €κ³ νλ©΄
μλ₯Ό λ€μ΄ Olivia
λΌλ μμκ° μ€λ³΅λμ΄ μλ€λ μ€λͺ
κ³Ό ν¨κ» IllegalArgumentException
μ΄ λ°μνλ€.
8.1.3 맡 ν©ν 리
1
2
Map<String, Integer> ageOfFriends
= Map.of("Raphael", 30, "Olivia", 25, "Thibaut", 26);
Map.of
ν©ν 리 λ©μλμ ν€μ κ°μ λ²κ°μ μ 곡νλ λ°©λ²μΌλ‘ 맡μ λ§λ€ μ μλ€.
μ΄ κ° μ΄νμ ν€ κ° μμμλ μ΄ λ©μλκ° μ μ©νμ§λ§, κ·Έ μ΄μμμλ Map.Entry<K, V>
κ°μ²΄λ₯Ό μΈμλ‘ λ°μΌλ©° κ°λ³ μΈμλ‘ κ΅¬νλ Map.ofEntries
λ₯Ό μ΄μ©νμ.
1
2
3
4
Map<String, Integer> ageOfFriends =
Map.ofEntries(entry("Raphael", 30),
entry("Olivia", 25),
entry("Thibaut", 26));
8.2 리μ€νΈμ μ§ν© μ²λ¦¬
μλ° 8μμλ List, Set μΈν°νμ΄μ€μ λ€μκ³Ό κ°μ λ©μλλ₯Ό μΆκ°νλ€.
- removeIf : Predicate λ₯Ό λ§μ‘±νλ μμλ₯Ό μ κ±°νλ€.
- replaceAll : List μμ UnaryOperation ν¨μλ₯Ό μ΄μ©ν΄ μμλ₯Ό λ°κΎΌλ€.
- sort : List λ₯Ό μ λ ¬νλ€.
μ΄λ€μ μλ‘μ΄ κ²°κ³Όλ₯Ό λ§λλ κ²μ΄ μλλΌ νΈμΆν 컬λ μ μ체λ₯Ό λ°κΎΌλ€.
8.2.1 removeIf λ©μλ
1
2
3
4
5
for (Transaction transaction : transactions) {
if (Character.isDigit(transaction.getReferenceCode().charAt(0))) {
transactions.remove(transaction);
}
}
μ΄λ μ«μλ‘ μμλλ μ°Έμ‘° μ½λλ₯Ό κ°μ§ νΈλμμ μ μμ νλ μ½λμ΄λ€.
λλ ConcurrentModificationException
μ λ°μμν¨λ€.
λ΄λΆμ μΌλ‘ for-each 루νλ Iterator
κ°μ²΄λ₯Ό μ¬μ©νκΈ° λλ¬Έμ λ€μκ³Ό κ°μ΄ ν΄μλλ€.
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))) {
transactions.remove(transaction);
}
}
κ²°κ³Όμ μΌλ‘ λ°λ³΅μμ μνμ 컬λ μ μ μνμ μλ‘ λκΈ°νλμ§ μλλ€.
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 λ©μλλ‘ λ°κΏ μ μλ€.
μ½λκ° λ¨μν΄μ§ λΏ μλλΌ λ²κ·Έλ μλ°©ν μ μλ€.
1
2
transactions.removeIf(transaction ->
Character.isDigit(transaction.getReferenceCode.charAt(0)));
8.2.2 replaceAll λ©μλ
1
2
3
referenceCodes.stream()
.map(code -> Character.toUpperCase(code.charAt(0)) + code.substring(1))
.collect(Collectors.toList())
μ€νΈλ¦Ό API λ₯Ό μ΄μ©ν΄ 리μνΈμ κ° μμλ₯Ό μλ‘μ΄ μμλ‘ λ°κΏ μ μλ€.
νμ§λ§ μ΄ μ½λλ μ λ¬Έμμ΄ μ»¬λ μ μ λ§λ λ€. κΈ°μ‘΄ 컬λ μ μ λ°κΎΈλ €λ©΄ ListIterator κ°μ²΄λ₯Ό μ΄μ©νλ€.
1
2
3
4
for (ListIterator<String> iterator = referenceCodes.listIterator(); iterator.hasNext(); ){
String code = iterator.next();
iterator.set(Character.toUpperCase(code.charAt(0)) + code.substring(1));
}
μ½λκ° λ³΅μ‘ν΄μ‘κ³ μ»¬λ μ
κ°μ²΄μ Iterator
κ°μ²΄λ₯Ό νΌμ©νλ©΄ λ°λ³΅κ³Ό λμμ 컬λ μ
λ³κ²½μ΄ μ΄λ£¨μ΄μ§λ©° μ½κ² λ¬Έμ λ₯Ό μΌμΌν¨λ€.
1
refereceCodes.replaceAll(code -> Character.toUpperCase(code.charAt(0)) + code.substring(1));
8.3 맡 μ²λ¦¬
8.3.1 forEach λ©μλ
Map.Entry<K, V>
μ λ°λ³΅μλ₯Ό μ΄μ©ν΄ 맡μ νλͺ© μ§ν©μ λ°λ³΅ν μ μλ€.
1
2
3
4
for(Map.Entry<String, Integer> entry: ageOfFriends.entrySet()) {
String friend = entry.getKey();
Integer age = entry.getValue();
}
μλ° 8μμλΆν° Map μΈν°νμ΄μ€λ BiConsumer
λ₯Ό μΈμλ‘ λ°λ forEach
λ©μλλ₯Ό μ§μνλ€.
1
ageOfFriends.forEach((friends, age) -> System.out.println(friend + age));
8.3.2 μ λ ¬ λ©μλ
λ€μ λ κ°μ μλ‘μ΄ μ νΈλ¦¬ν°λ₯Ό μ΄μ©νμ¬ λ§΅μ νλͺ©μ κ° λλ ν€λ₯Ό κΈ°μ€μΌλ‘ μ λ ¬ν μ μλ€.
- Entry.comparingByValue
- Entry.comparingByKey
1
2
3
4
5
favouriteMovies
.entrySet()
.stream()
.sorted(Entry.comparingByKey())
.forEachOrdered(System.out::println);
μλ° 8μμλ HashMap
μ λ΄λΆ ꡬ쑰λ₯Ό λ°κΏ μ±λ₯μ κ°μ νλ€.
κΈ°μ‘΄ 맡μ ν€λ‘ μμ±ν ν΄μμ½λλ‘ μ κ·Όν μ μλ ν·μ μ μ₯νλ€.
λ€λ§ λ§μ ν€κ° κ°μ ν΄μμ½λλ₯Ό λ°ννλ©΄ O(n)
μ μκ°μ΄ 걸리λ LinkedList
λ‘ λ²ν·μ λ°ννμ¬ μ±λ₯μ΄ μ νλλ€.
μ΅κ·Όμλ λ²ν·μ΄ λ무 μ»€μ§ κ²½μ° μ΄λ₯Ό O(log n)
μΌλ‘ μμλλ μ λ ¬λ νΈλ¦¬λ₯Ό μ΄μ©ν΄ λμ μΌλ‘ μΉννμ¬ μ±λ₯μ κ°μ νλ€.
λ€λ§ μ΄λ key κ°μ΄ String ,Number κ°μ Comparable ννμ¬μΌλ§ μ§μλλ€.
8.3.3 getOrDefault λ©μλ
κΈ°μ‘΄μλ ν€κ° μ‘΄μ¬νμ§ μμΌλ©΄ null μ΄λ―λ‘ NullPointerException
μ λ°©μ§νλ €λ©΄ λ 체ν¬κ° νμνλ€.
κΈ°λ³Έκ°μ λ°ννλ λ°©μμΌλ‘ μ΄λ₯Ό ν΄κ²°ν μ μλ€.
1
2
3
4
Map<String, String> favouriteMovies =
Map.ofEntries(entry("Raphael", "Star Wars"), entry("Olivia", "James Bond"));
favouriteMovies.getOrDefault("Olivia", "Matrix"));
첫 λ²μ§Έ μΈμμΈ ν€κ° μ‘΄μ¬νμ§ μμΌλ©΄ λ λ²μ§Έ μΈμμΈ κΈ°λ³Έκ°μ λ°ννλ€.
8.3.4 κ³μ° ν¨ν΄
ν€λ₯Ό μ΄μ©ν΄ κ°λΉμΌ λμμ μ€νν΄μ μ»μ κ²°κ³Όλ₯Ό μΊμνλ € νλ€.
- computeIfAbsent : μ 곡λ ν€μ ν΄λΉνλ κ°μ΄ μμΌλ©΄, ν€λ₯Ό μ΄μ©ν΄ μ κ°μ κ³μ°νκ³ λ§΅μ μΆκ°
- computeIfPresent : μ 곡λ ν€κ° μ‘΄μ¬νλ©΄ μ κ°μ κ³μ°νκ³ λ§΅μ μΆκ°
- compute : μ 곡λ ν€λ‘ μ κ°μ κ³μ°νκ³ λ§΅μ μ μ₯
μ¬λ¬ κ°μ μ μ₯νλ 맡μ μ²λ¦¬ν λλ μ΄ ν¨ν΄μ νμ©ν μ μλ€.
1
2
3
4
5
6
7
String friend = "Raphael";
List<String> movies = friendsToMovies.get(friend);
if (movies == null) {
movies = new ArrayList<>();
friendsToMovies.put(friend, movies);
}
movies.add("Star Wars");
μ΄λ₯Ό computeIfAbsent
λ₯Ό νμ©νλ©΄
1
2
friendsToMovie.computeIfAbsent("Raphael", name -> newArrayList<>())
.add("Star Wars");
μ΄ λ©μλλ νμ¬ ν€κ³Ό κ΄λ ¨λ κ°μ΄ 맡μ μ‘΄μ¬νλ©° null μ΄ μλ λλ§ μ κ°μ κ³μ°νλ€.
8.3.5 μμ ν¨ν΄
1
2
3
4
5
6
7
String key = "Raphael";
String value = "Jack Reacher 2";
if (favouriteMovies.containsKey(key) && Objects.equals(favouriteMovies.get(key), value)) {
favouriteMovies.remove(key);
return true;
}
return false;
μ΄λ₯Ό λ€μμ²λΌ κ°κ²°νκ² κ΅¬νν μ μλ€.
1
favouriteMovies.remove(key, value);
8.3.6 κ΅μ²΄ ν¨ν΄
- replaceAll :
BiFunction
μ μ μ©ν κ²°κ³Όλ‘ κ° νλͺ©μ κ°μ κ΅μ²΄νλ€. - Replace : ν€κ° μ‘΄μ¬νλ©΄ 맡μ κ°μ λ°κΎΌλ€.
1
2
Map<String, String> favouriteMovies = new HashMap<>();
favouriteMovies.replaceAll((friend, movie) -> movie.toUpperCase());
맡μ λͺ¨λ κ°μ νμμ λ°κΏ μ μλ€.
8.3.7 ν©μΉ¨
λ κ°μ 맡μμ κ°μ ν©μΉκ±°λ λ°κΏμΌ νλ€λ©΄ merge
λ©μλλ₯Ό μ΄μ©ν μ μλ€.
λ κ·Έλ£Ήμ μ°λ½μ²λ₯Ό ν¬ν¨νλ λ 맡μ ν©μΉλ€κ³ κ°μ νλ€.
1
2
3
4
5
6
7
8
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
λ©μλλ₯Ό μ΄μ©νμ.
λ§μ½ λ 맡 λͺ¨λμ Cristina κ° λ€λ₯Έ μν κ°μΌλ‘ μ‘΄μ¬νλ€κ³ κ°μ νμ.
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"), entry("Cristina", "Matrix"));
forEach μ merge λ₯Ό μ΄μ©ν΄ μΆ©λμ ν΄κ²°ν μ μλ€..
1
2
3
Map<String, String> everyone = new HashMap<>(family);
friends.forEach((k, v) ->
everyone.merge(k, v, (movie1, movie2) -> movie1 + " & " + movie2));
μ§μ λ ν€μ μ°κ΄λ κ°μ΄ μκ±°λ null μ΄λ©΄ null μ΄ μλ κ°κ³Ό μ°κ²°νλ€.
κ·Έλ μ§ μμΌλ©΄ 맀ν ν¨μμ κ²°κ³Ό κ°μΌλ‘ λμΉνκ±°λ νλͺ©μ μ κ±°νλ€.
μ΄κΈ°ν κ²μ¬λ₯Ό ꡬνν μλ μλ€.
1
moviesToCount.merge(movieName, 1L, (key, count) -> count + 1L);
8.4 κ°μ λ ConcurrentHashMap
λμμ± μΉνμ μ΄λ©° μ΅μ κΈ°μ μ λ°μν HashMap λ²μ μ΄λ€.
λ΄λΆ μλ£κ΅¬μ‘°μ νΉμ λΆλΆλ§ μ κΆ λμ μΆκ°, κ°±μ μμ μ νμ©νλ€.
λ°λΌμ λκΈ°νλ HashTable λ²μ μ λΉν΄ μ½κΈ° μ°κΈ° μ°μ° μ±λ₯μ΄ μλ±νλ€.
8.4.1 리λμ€μ κ²μ
μ€νΈλ¦Όκ³Ό λΉμ·ν μ’ λ₯μ μΈ κ°μ§ μλ‘μ΄ μ°μ°μ μ§μνλ€.
- forEach : κ° key, value μμ μ£Όμ΄μ§ μ‘μ μ μ€ν
- reduce : λͺ¨λ key, value μμ ν©μΉ¨
- search : null μ΄ μλ κ°μ λ°νν λκΉμ§ key, value μμ ν¨μλ₯Ό μ μ©
λ€μμ²λΌ ν€μ ν¨μ λ°κΈ°, κ°, Map.Entry, (key, value) μΈμλ₯Ό μ΄μ©ν λ€ κ°μ§ μ°μ° ννλ₯Ό μ§μνλ€.
- (key, value)λ‘ μ°μ° : forEach, reduce, search
- keyλ‘ μ°μ° : forEachKey, reduceKeys, searchKeys
- value λ‘ μ°μ° : forEachValue, reduceValue, searchValue
- Map.Entry κ°μ²΄λ‘ μ°μ° : forEachEntry, reduceEntries, searchEntries
μ΄λ€ μ°μ°μ ConcurrentHashMap
μ μνλ₯Ό μ κ·Έμ§ μκ³ μ°μ°μ μννλ€.
λν λ³λ ¬μ± κΈ°μ€κ°μ κΈ°μ ν΄μΌ νλ€.
맡μ ν¬κΈ°κ° μ£Όμ΄μ§ κΈ°μ€κ°λ³΄λ€ μμΌλ©΄ μμ°¨μ μΌλ‘ μ°μ°μ μ€ννλ€.
κΈ°μ€κ°μ 1λ‘ μ§μ νλ©΄ κ³΅ν΅ μ€λ λ νμ μ΄μ©ν΄ λ³λ ¬μ±μ κ·Ήλννλ€.
Long.MAX_VALUE λ‘ μ§μ νλ©΄ ν κ°μ μ€λ λλ§μΌλ‘ μ°μ°μ μ€ννλ€.
8.4.2 κ³μ
맡μ 맀ν κ°μλ₯Ό λ°ννλ mappingCount
λ©μλλ₯Ό μ 곡νλ€.
κΈ°μ‘΄μ size λ©μλ λμ int λ₯Ό λ°ννλ mappingCount
λ©μλλ₯Ό μ¬μ©νλ κ²μ΄ μ’λ€.
8.4.3 μ§ν©λ·°
μ§ν©λ·°λ‘ λ°ννλ keySet
μ΄λΌλ λ©μλλ₯Ό μ 곡νλ€.
맡μ λ°κΎΈλ©΄ μ§ν©λ λ°λκ³ , μ§ν©μ λ°κΎΈλ©΄ 맡λ μν₯μ λ°λλ€.