CHAP08 - Modern-Java-in-Action/Online-Study GitHub Wiki
- ์์ ๋ฆฌ์คํธ, ์งํฉ, ๋งต์ ์ฝ๊ฒ ๋ง๋ค ์ ์๋๋ก ๊ฐ์ ๋ ์ปฌ๋ ์ ํฉํ ๋ฆฌ
- ๋ฆฌ์คํธ์ ์งํฉ์์ ์์๋ฅผ ์ญ์ ํ๊ฑฐ๋ ๋ฐ๊พธ๋ ๊ด์ฉ ํจํด ์ ์ฉ ๋ฐฉ๋ฒ
- ๋งต ์์ ๊ณผ ๊ด๋ จํด ์ถ๊ฐ๋ ์๋ก์ด ํธ๋ฆฌ ๊ธฐ๋ฅ
โ
-
ํฉํ ๋ฆฌ ๋ฉ์๋ : ๊ฐ์ฒด ์์ฑ ์ฝ๋๋ฅผ ๋ณ๋ ํด๋์ค/๋ฉ์๋๋ก ๋ถ๋ฆฌํ์ฌ ๊ฐ์ฒด ์์ฑ์ ๋ณํ์ ๋๋นํ๋ ๋ฐ ์ ์ฉํ๋ค.
-
new Integer(0)
๋์ ์ฌ์ฉํ๋Intege.valueOf(0)
- Design Pattern ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ด๋ - Heee's Development Blog (gmlwjd9405.github.io)
-
-
๊ฐ์ฒด๋ฅผ final ํค์๋๋ก ์ ์ธํด๋, ๋ด๋ถ ๋ฐ์ดํฐ๋ ๋ฐ๊ฟ ์ ์๋ค.
final Person p = new Person("Bob", 30); //p = new Person("John", 25); p.name = "John"; p.age = 25; private static class Person{ public String name; public int age; Person(String name, int age){ this.name = name; this.age = age; } }
โ
- ์๋ฐ 9๋ ์ ์ ์์๋ฅผ ํฌํจํ๋ฉฐ ๋ฐ๊ฟ ์ ์๋ ๋ฆฌ์คํธ, ์งํฉ, ๋งต์ ์ฝ๊ฒ ๋ง๋ค ์ ์๋๋ก List.of, Set.of, Map.of, Map.ofEntries ๋ฑ ์ปฌ๋ ์ ํฉํ ๋ฆฌ๋ฅผ ์ง์ํ๋ค.
- List ์ธํฐํ์ด์ค์์ removeIf, replaceAll, sort ์ธ ๊ฐ์ง ๋ํดํธ ๋ฉ์๋๋ฅผ ์ง์ํ๋ค.
- Set ์ธํฐํ์ด์ค๋ removeIf ๋ํดํธ ๋ฉ์๋๋ฅผ ์ง์ํ๋ค.
- Map ์ธํฐํ์ด์ค๋ ์์ฃผ ์ฌ์ฉํ๋ ํจํด๊ณผ ๋ฒ๊ทธ๋ฅผ ๋ฐฉ์งํ ์ ์๋๋ก ๋ค์ํ ๋ํดํธ ๋ฉ์๋๋ฅผ ์ง์ํ๋ค.
- ConcurrentHashMap์ Map์์ ์์๋ฐ์ ์ ๋ํดํธ ๋ฉ์๋๋ฅผ ์ง์ํจ๊ณผ ๋์์ ์ค๋ ๋ ์์ ์ฑ๋ ์ ๊ณตํ๋ค.
๊ตฌ๋ถ | ๋ฉ์๋ | ์ค๋ช |
---|---|---|
๊ณตํต | List.of, Set.of, Map.of | ๋ฐ๊ฟ ์ ์๋ ๋ฆฌ์คํธ/์งํฉ/๋งต ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. |
๋ฆฌ์คํธ/์งํฉ | removeIf | ํ๋ฆฌ๋์ผ์ดํธ๋ฅผ ๋ง์กฑํ๋ ์์๋ฅผ ์ ๊ฑฐ |
replaceAll | UnaryOperator ํจ์๋ก ์์๋ฅผ ๋ฐ๊ฟ | |
sort | ์ ๋ ฌ | |
๋งต | forEach | Biconsumer๋ฅผ ๋๊ฒจ ํค์ ๊ฐ์ ๋ฐ๋ณตํ์ฌ ์ฒ๋ฆฌ |
sorted | ์ ๋ ฌ | |
getOrDefault | ์ฐพ์ผ๋ ค๋ ํค๊ฐ ์กด์ฌํ์ง ์์๋ ๋ฐํํ ๊ธฐ๋ณธ๊ฐ์ ์ง์ | |
computeIfAbsent | ์ ๊ณต๋ ํค์ ํด๋นํ๋ ๊ฐ์ด ์์ผ๋ฉด, ํค๋ก ์ ๊ฐ์ ๊ณ์ฐํ๊ณ ๋งต์ ์ถ๊ฐ | |
computeIfPresent | ์ ๊ณต๋ ํค์ ํด๋นํ๋ ๊ฐ์ด ์์ผ๋ฉด, ํค๋ฅผ ์ด์ฉํด ์ ๊ฐ์ ๊ณ์ฐํ๊ณ ๋ณ๊ฒฝ | |
compute | ์ ๊ณต๋ ํค๋ก ์ ๊ฐ์ ๊ณ์ฐํ๊ณ ์ ์ฅ | |
remove | ํค/๊ฐ์ ์ธ์๋ก ๋ฐ์ ํด๋น๋๋ ๋ฐ์ดํฐ๋ฅผ ์ญ์ | |
replaceAll | BiFunction์ ์ ์ฉํ ๊ฒฐ๊ณผ๋ก ๊ฐ ํญ๋ชฉ์ ๊ฐ์ ๊ต์ฒด | |
replace | ํค๊ฐ ์กด์ฌํ๋ฉด ๋งต์ ๊ฐ์ ๋ฐ๊ฟ | |
merge | ํค, ๊ฐ, ํค ์ค๋ณต์ ์ฒ๋ฆฌํ BiFunctino์ ์ธ์๋ก ๋๊ธบ | |
ConcurrentHashMap | forEach | ํค/๊ฐ ์์ ์ฃผ์ด์ง ์ก์ ์ ์คํ |
reduce | ๋ชจ๋ ํค/๊ฐ ์์ ์ ๊ณต๋ ๋ฆฌ๋์ค ํจ์๋ฅผ ์ด์ฉํด ํฉ์นจ | |
search | null ์๋ ๊ฐ์ ๋ฐํํ ๋๊น์ง ํค/๊ฐ์ ํจ์๋ฅผ ์ ์ฉ | |
mappingCount | long์ ๋ฐํ(๊ธฐ์กด size๋ int) | |
keySet | ํค๊ฐ์ ์งํฉ์ผ๋ก ๋ณํ, ์งํฉ/๋งต์ ์๋ก ๋ณ๊ฒฝ์ฌํญ์ด ๋๊ธฐํ๋จ |
maven ํ๋ก์ ํธ์์ pom.xml์ ์๋์ ๊ฐ์ด ์์กด์ฑ์ ์ถ๊ฐํ๋ค.
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.17.4</version>
</dependency>
Faker ๊ฐ์ฒด๋ฅผ ์์ฑํด ์์์ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ ์ ์๋ค.
Faker faker = new Faker();
documents = new HashMap<>();
for(int i=0; i<10; i++){
documents.put(faker.dune().character(), faker.dune().planet());
}
documents.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(System.out::println);
documents.forEach((name, address)->System.out.println(name+" : "+address));
System.out.println(documents.getOrDefault("Chani", "NOT_FOUND_CHANI"));
์ง์ํ๋ ๋ฐ์ดํฐ์ : ์ฃผ์, ์ด๋ฆ, ํญ๊ณต๊ธฐ, ์ฝ์ธ, ๊ณ ์์ด, ์ ๋ฑ 82์ข
DiUS/java-faker: Brings the popular ruby faker gem to Java (github.com)
java faker ๋ก ํ ์คํธ ๋ฐ์ดํ ๋ง๋ค๊ธฐ (lesstif.com)
](https://www.lesstif.com/java/java-faker-48988763.html)
HashMap<String, String> documents = new HashMap<>();
Faker faker = new Faker();
for(int i=0; i<100000; i++){
documents.put(faker.name().fullName(), faker.address().fullAddress());
}
//documents.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(System.out::println);
//documents.forEach((name, address)->System.out.println(name+" : "+address));
//System.out.println(documents.getOrDefault("Chani", "NOT_FOUND"));
//documents.entrySet().stream().parallel().sorted(Map.Entry.comparingByKey()).limit(10).forEachOrdered(System.out::println);
System.out.println("# filter startWith A, limit 10");
documents.entrySet().stream().filter(e -> e.getKey().startsWith("A")).limit(10).forEach(System.out::println);
System.out.println("\n# distinct, limit 10");
documents.entrySet().stream().distinct().limit(10).forEach(System.out::println);
System.out.println("\n# map address -> length, limit 10");
documents.entrySet().stream().map(e -> e.getValue().length()).limit(10).forEach(System.out::println);
System.out.println("\n# collect, joining string");
System.out.println(documents.keySet().stream().limit(10).collect(joining(" ")));
System.out.println("\n# collect, reducing for joining string");
System.out.println(documents.keySet().stream().limit(10).collect(reducing("", (o, v)->o+","+v)));
System.out.println("\n# reduce for joining string");
System.out.println(documents.keySet().stream().limit(10).reduce("", (o, v)->o+","+v));
System.out.println("\n# replaceAll name toUpperCase, limit 10");
documents.replaceAll((k,v)->k.toUpperCase());
documents.entrySet().stream().limit(10).forEach(System.out::println);
- Arrays.asList๋ก ๋ง๋ ๋ฆฌ์คํธ๋ ๋ฐ์ดํฐ๊ฐ final ๋ฐฐ์ด์ ๋ด๊ฒจ ์๋ค.
- ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ ์ ์๊ณ , ๋ด๋ถ ๋ฐ์ดํฐ๋ ๋ฐ๊ฟ ์ ์๋ค.
๊ธฐ์กด ์๋ฐ์์ ์๋ ์ฝ๋๋ UnsupportedException
์ ๋ฑ๋๋ค.
List<String> friends2 = Arrays.asList("Rael", "Oli");
friends2.set(0, "Rich");
friends2.add("Thiba"); //์์ธ๋ฐ์
์๋ํ๋ฉด Arrays.asList
๋ ์์ฒด ์ ์ํ private ArrayList๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์ด๋ค. ๊ณ ์ ํฌ๊ธฐ final ๋ฐฐ์ด์ ๋ง๋ค์ด ์ด๊ธฐํํ ํ์๋ ์ ๋ฐฐ์ด๋ก ๋ฐ๊พธ์ง ๋ชปํ๊ฒ ํ๊ณ , ๋ด๋ถ ๋ฐ์ดํฐ๋ง ๋ณ๊ฒฝํ ์ ์๋ค. ๊ทธ๋์ AbstractList ์ถ์ํด๋์ค๋ set, add ๋ชจ๋ UnsupportedException
์์ธ๋ฅผ ๋์ง๋๋ฐ, ๊ทธ์ค set ๋ฉ์๋๋ง ์ฌ์ ์ํด๋์๋ค.
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private final E[] a;
@Override
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element;
return oldValue;
}
}
- List.of๋ก ๋ง๋ ๋ฆฌ์คํธ๋ ๋ฐ์ดํฐ๊ฐ final ๋ฐฐ์ด์ ๋ด๊ฒจ ์๋ค.
- ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐ/์์ /์ญ์ ํ๋ ๋ชจ๋ ๋ฉ์๋๊ฐ ์์ธ๋ฅผ ๋์ง๋ค.
- ์์ฑ์์์ 10๊ฐ ์ดํ ์ธ์๋ ๊ณ ์ ํฌ๊ธฐ ๋ฐฐ์ด๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋๋ค. ์ธ์ ๊ฐ์๊ฐ ๊ทธ ์ด์์ธ ๊ฒฝ์ฐ ๋ฐฐ์ดํฌ๊ธฐ๋ฅผ ๋๋ ค๊ฐ๋ฉฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๊ณ , ๊ฐ๋น์ง ์ปฌ๋ ์ ๋น์ฉ์ด ์ถ๊ฐ๋ก ๋ค์ด๊ฐ๋ค.
๋ค์ ์ฝ๋์์๋ add/set ๋ฉ์๋ ํธ์ถ์ UnsupportedException
์ ๋ฑ๋๋ค.
List<String> friends = List.of("Rael", "Oli", "Thiba");
friends.add("Taey"); //์์ธ๋ฐ์
friends.set(0, "Taey"); //์์ธ๋ฐ์
List.of
๋ ImmutableCollections.ListN<>()
๋ฅผ ๋ฐํํ๋ค. ListN์ AbstractImmutableList์ ์์ํ๋ ์ ์ ํด๋์ค์ด๊ณ , AbstractImmutableList๋ ์๋์ ๊ฐ์ด final ๋ฐฐ์ด๋ก ๋ฐ์ดํฐ๋ฅผ ๋ด๊ณ , ๋ฆฌ์คํธ๋ฅผ ์์ ํ๋ ๋ชจ๋ ๋ฉ์๋์์ ์์ธ๋ฅผ ๋์ง๋๋ก ์ค๊ณ๋์ด ์๋ค.
static final class ListN<E> extends AbstractImmutableList<E>
implements Serializable {
static final List<?> EMPTY_LIST = new ListN<>();
@Stable
private final E[] elements;
}
static abstract class AbstractImmutableList<E> extends AbstractImmutableCollection<E>
implements List<E>, RandomAccess {
// all mutating methods throw UnsupportedOperationException
// uoe()๋ UnsupportedException์ ๋์ง๋ ๋ฉ์๋
@Override public void add(int index, E element) { throw uoe(); }
@Override public boolean addAll(int index, Collection<? extends E> c) { throw uoe(); }
@Override public E remove(int index) { throw uoe(); }
@Override public void replaceAll(UnaryOperator<E> operator) { throw uoe(); }
@Override public E set(int index, E element) { throw uoe(); }
@Override public void sort(Comparator<? super E> c) { throw uoe(); }
}
- Set.of๋ก ๋ฐ๊ฟ ์ ์๋ ์งํฉ์ ๋ง๋ค ์ ์๋ค.
- ์ค๋ณต๋ ๋ฐ์ดํฐ๋ฅผ ๋๊ธฐ๋ฉด ์์ธ๋ฅผ ๋์ง๋ค.
Set<String> friends = Set.of("Rael", "Oli", "Thiba");
Set<String> friends2 = Set.of("Rael", "Oli", "Thiba", "Rael"); //์์ธ๋ฐ์
//Stream์ ์ฌ์ฉํด ์ ์ผํ ๊ฐ์ ์ถ์ถํ ์๋ ์์ง๋ง, ๊ณ ์ ํฌ๊ธฐ๋ก ๊ฐ๋ฒผ์ด ์งํฉ์ ๋ง๋ค๋ ค๋ ์๋์์ ํ์ฐธ ๋ฒ์ด๋ ๋ฒ๋ฆฐ๋ค.
Set<String> friends3 = List.of("Rael", "Oli", "Thiba", "Rael").stream().distinct().collect(toSet());
- Map.of๋ก ๋ฐ๊ฟ ์ ์๋ ๋งต์ ๋ง๋ค ์ ์๋ค.
- entry๋ Map.Entry ๊ฐ์ฒด๋ฅผ ๋ง๋๋ ํฉํ ๋ฆฌ ๋ฉ์๋์ด๋ฉฐ, ๋ด๋ถ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ค.
Map<String, Integer> ageOfFriends = Map.of("Rael", 30, "Oli", 25, "Thiba", 26);
Map<String, Integer> ageOfFriends2 = Map.ofEntries(
entry("Rael", 30),
entry("Oli", 25),
entry("Thiba", 26)
);
๋ค์ ์ฝ๋์ ์คํ๊ฒฐ๊ณผ๋?
List<String> actors = List.of("Keanu", "Jessica");
actors.set(0, "Brad");
System.out.println(actors);
- removeIf : ํ๋ฆฌ๋์ผ์ดํธ๋ฅผ ๋ง์กฑํ๋ ์์๋ฅผ ์ ๊ฑฐ, List๋ Set์ ๊ตฌํํ๊ฑฐ๋ ๊ทธ ๊ตฌํ์ ์์๋ฐ์ ๋ชจ๋ ํด๋์ค์์ ์ด์ฉ.
removeIf๋ฅผ ์ฌ์ฉํ์ง ์์ ๋
์ปฌ๋ ์
์์ ํน์ ๊ฐ์ฒด๋ฅผ ๊ณจ๋ผ์ ์ญ์ ํ๋ ค๋ฉด? for-each๋ ๋ด๋ถ์ ์ผ๋ก Iterator๋ฅผ ์ฌ์ฉํ๋ค. ๋ฆฌ์คํธ๋ฅผ ์ํํ๋ ๋ฐ Iterator๋ฅผ ์ฌ์ฉํ๊ณ , ๋ฆฌ์คํธ์์ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ ๋ฐ ์ปฌ๋ ์
์ผ๋ก ์ ๊ทผํ๋ฉด ๋ ๊ฐ์ฒด๊ฐ ๋๊ธฐํ๊ฐ ์ด๋ค์ง์ง ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค. ๊ทธ๋์ ์๋ ์ฝ๋๋ ConcurrentModificationException
์ ๋์ง๋ค.
TestData td = new TestData();
for(Person p : td.people){
if(p.age > 50) td.people.remove(p);
}
์ ์ฝ๋๋ ์๋์ ๊ฐ์ด ํด์๋๋ค.
for(Iterator<Peorson> itr = td.people.iterator(); iterator.hasNext(); ){
Person p = itr.next();
/* ์๋ต */
}
์๋ํ ๋๋ก ์๋์ํค๋ ค๋ฉด ์๋์ฒ๋ผ ๋ช ์์ ์ผ๋ก Iterator๋ฅผ ์ฌ์ฉํ๊ณ remove ๋ฉ์๋๋ฅผ ํธ์ถํด์ผ ํ๋ค.
for(Iterator<Peorson> itr = td.people.iterator(); iterator.hasNext(); ){
Person p = itr.next();
if(p.age > 50) itr.remove();
}
removeIf๋ฅผ ์ฌ์ฉํ ๋
ํ๋ฆฌ๋์ผ์ดํธ๋ฅผ ์ธ์๋ก ๋๊ฒจ ๊ฐ๋จํ ์ฒ๋ฆฌํ ์ ์๋ค.
td.people.removeIf(p -> p.age>50);
- replaceAll : ๋ฆฌ์คํธ์์ ์ด์ฉํ ์ ์๋ ๊ธฐ๋ฅ์ผ๋ก UnaryOperator ํจ์๋ฅผ ์ด์ฉํด ์์๋ฅผ ๋ฐ๊ฟ.
replaceAll์ ์ฌ์ฉํ์ง ์์ ๋
์๋์ ๊ฐ์ด ์คํธ๋ฆผ์ ์ฌ์ฉํด ๋งคํํ ์ ์์ง๋ง ์๋ก์ด ๋ฌธ์์ด ๋ฆฌ์คํธ๋ฅผ ์์ฑํ๋ค.
TestData td = new TestData();
td.people.stream()
.map(p -> p.name.toLowerCase())
.collect(Collectors.toList())
.forEach(System.out::println);
๊ธฐ์กด ์ปฌ๋ ์ ์ ๋ฐ๊พธ๋ ค๋ฉด ์๋์ ๊ฐ์ด Iterator์ set() ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผํ๋ค.
for(ListIterator<Person> itr = td.people.listIterator(); itr.hasNext(); ){
Person p = itr.next();
itr.set(changeName(p));
}
replaceAll์ ์ฌ์ฉํ ๋
td.people.replaceAll(ListSetProcessor::changeName);
td.people.sort((o1, o2) -> Integer.compare(o1.age, o2.age));
์๋ ์ฝ๋๋ฅผ ์งง๊ฒ ์ค์ด๋ ค๋ฉด?
Map<String, Integer> movies = new HashMap<>();
movies.put("JamesBond", 20);
movies.put("Matrix", 15);
movies.put("Harry Potter", 5);
Iterator<Map.Entry<String, Integer>> iterator = movies.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<String, Integer> entry = iterator.next();
if(entry.getValue() < 10){
iterator.remove();
}
}
์ ๋ต
movies.entrySet().removeIf(e -> e.getValue()<10);
โ
๋งต์์ ํค์ ๊ฐ์ ๋ฐ๋ณตํ์ฌ ํ์ธํ๋ ์์ ์ for๋ฌธ๊ณผ entrySet์ ์ฌ์ฉํ๋ค.
Map<String, Integer> ageOfFriends = new HashMap<>();
ageOfFriends.put("๊น์ด๋ฆ", 30);
ageOfFriends.put("์ด์ต๋ช
", 40);
ageOfFriends.put("๋ฐ๋๋ค์", 50);
for(Map.Entry<String, Integer> entry : ageOfFriends.entrySet()){
String name = entry.getKey();
Integer age = entry.getValue();
System.out.println(name + " is " + age + " years old.");
}
์ด์ ๋ forEach์ ํค์ ๊ฐ์ ์ธ์๋ก ๋ฐ๋ BiConsumer๋ฅผ ๋๊ฒจ ์ฒ๋ฆฌํ ์ ์๋ค.
ageOfFriends.forEach((name, age)->System.out.println(name+" is "+age+" years old."));
HashMap์ ์ ๋ ฌํ ๋, EntrySet์ ๋ณ๋ Collection ๊ฐ์ฒด๋ก ๋ง๋ค์ด์ Collections.sort๋ก ์ ๋ ฌํ์ง ์์๋ ๋๋ค. ์๋์ ๊ฐ์ด sorted ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
Map<String, String> favouriteMoview = Map.ofEntries(
entry("Rahpael", "Star Wars"),
entry("Cristina", "Matrix"),
entry("Olivia", "James bond"));
favouriteMoview
.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey())
//.forEach(System.out::println);
.forEachOrdered(System.out::println);
์๋ฐ8์์ HashMap์ ๋ง์ ํค๊ฐ ๊ฐ์ ํด์๊ฐ์ ๋ฐํํ๋ ๊ฒฝ์ฐ, O(logn) ์๊ฐ์ด ์์๋๋ ์ ๋ ฌ๋ ํธ๋ฆฌ๋ฅผ ์ด์ฉํด ๋์ ์ผ๋ก ์นํํ์ฌ ์ฑ๋ฅ์ ํฅ์์์ผฐ๋ค.
๊ธฐ์กด์๋ ์ฐพ์ผ๋ ค๋ ํค๊ฐ ์กด์ฌํ์ง ์์ผ๋ฉด null์ด ๋ฐํ๋๋ฏ๋ก NullPointerException์ด ๋ฐ์ํ ์ ์์๋ค. getOrDefault๋ก ๊ธฐ๋ณธ๊ฐ์ ์ง์ ํด์ค์ผ๋ก์จ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
Map<String, String> favouriteMovies = Map.ofEntries(
entry("Rahpael", "Star Wars"),
entry("Cristina", "Matrix"));
System.out.println(favouriteMovies.getOrDefault("Olivia", "Matrix"));
System.out.println(favouriteMovies.getOrDefault("Timothy", "Dune"));
๋จ, ํค๋ ์กด์ฌํ๊ณ ๊ฐ์ null์ธ ๊ฒฝ์ฐ ์ ์ฝ๋๋ก๋ NullPointerException์ ๋ง์ฃผํ ์ ์๋ค.
- computeIfAbsent : ์ ๊ณต๋ ํค์ ํด๋นํ๋ ๊ฐ์ด ์์ผ๋ฉด, ํค๋ฅผ ์ด์ฉํด ์ ๊ฐ์ ๊ณ์ฐํ๊ณ ๋งต์ ์ถ๊ฐ
- computeIfPresent : ์ ๊ณต๋ ํค์ ํด๋นํ๋ ๊ฐ์ด ์์ผ๋ฉด, ํค๋ฅผ ์ด์ฉํด ์ ๊ฐ์ ๊ณ์ฐํ๊ณ ๊ฐ์ ๋ณ๊ฒฝ
- compute : ์ ๊ณต๋ ํค๋ก ์ ๊ฐ์ ๊ณ์ฐํ๊ณ ๋งต์ ์ ์ฅํ๋ค.
ํ์ผ ํ์คํ์ค ํด์๊ฐ์ ๊ณ์ฐํด ์ ์ฅํ๋ ์ปฌ๋ ์ . computeIfAbsent๋ก ์ด๋ฏธ ์ฝ์ด์จ ์ค์ธ์ง ํ์ธํ๊ณ ํด์๊ฐ ๊ณ์ฐํด ์ถ๊ฐ.
try (Stream<String> lines = Files.lines(Paths.get("D:\\DailyLogs\\README.md"), Charset.defaultCharset())){
Map<String, byte[]> dataToHash = new HashMap<>();
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
this.messageDigest = messageDigest;
lines.forEach(line -> dataToHash.computeIfAbsent(line, this::calculateDigest));
} catch (NoSuchAlgorithmException | IOException e) {
e.printStackTrace();
}
์น๊ตฌ์ด๋ฆ/์ํ๋ชฉ๋ก ์ปฌ๋ ์ . ์น๊ตฌ ์ด๋ฆ์ ๊ฒ์ํด ์์ผ๋ฉด ์ ์ํ๋ชฉ๋ก์ ์์ฑํด ์ถ๊ฐ.
Map<String, List<String>> friendsToMovies = Map.ofEntries();
String friend = "Raphael";
List<String> movies = friendsToMovies.get(friend);
if(movies==null){
movies = new ArrayList<>();
friendsToMovies.put(friend, movies);
}
movies.add("Star Wars");
Map<String, List<String>> friendsToMovies2 = Map.ofEntries();
friendsToMovies2.computeIfAbsent("Rahpael", name -> new ArrayList<>())
.add("Star Wars");
๊ธฐ์กด์๋ ์๋์ ๊ฐ์ด ํค๋ฅผ ์ธ์๋ก ๋ฐ๋ remove ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋๋ฐ, ๊ทธ์ ์ ํด๋น ํค๊ฐ ์ปฌ๋ ์ ์ ์กด์ฌํ๋์ง ๊ทธ๋ฆฌ๊ณ ์ญ์ ํ๋ ค๋ ๋ฐ์ดํฐ์ ํค/๊ฐ๊ณผ ๋น๊ตํด์ผ ํ๋ค.
Map<String, String> favouriteMovies = new HashMap<>(Map.ofEntries(
entry("Rahpael", "Star Wars"),
entry("Cristina", "Matrix"),
entry("Olivia", "James bond")));
String key = "Raphael";
String value = "Jack Reacher 2";
if(favouriteMovies.containsKey(key) && Objects.equals(favouriteMovies.get(key), value)){
favouriteMovies.remove(key);
}
์ด์ ํค/๊ฐ์ ์ธ์๋ก ๋๊ฒจ ์ญ์ ํ ์ ์๋ค.
favouriteMovies.remove(key, value);
- replaceAll : BiFunction์ ์ ์ฉํ ๊ฒฐ๊ณผ๋ก ๊ฐ ํญ๋ชฉ์ ๊ฐ์ ๊ต์ฒดํ๋ค. ์ด ๋ฉ์๋๋ ์ด์ ์ ์ดํด๋ณธ List์ replaceAll๊ฐ ๋น์ทํ ๋์์ ํ๋ค.
- replace : ํค๊ฐ ์กด์ฌํ๋ฉด ๋งต์ ๊ฐ์ ๋ฐ๊พผ๋ค. ํค๊ฐ ํน์ ๊ฐ์ผ๋ก ๋งคํ๋์์ ๋๋ง ๊ฐ์ ๊ต์ฒดํ๋ ์ค๋ฒ๋ก๋ ๋ฒ์ ๋ ์๋ค.
favouriteMovies.replaceAll((friend, movie) -> movie.toUpperCase());
๋ ๋งต์ ํฉ์น ๋ ์ค๋ณต๋ ํค/๊ฐ์ด ์๋ค๋ฉด ์๋ํ์ง ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์๋ค.
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"));
Map<String, String> everyone = new HashMap<>(family);
everyone.putAll(friends);
BiFunction์ ์ธ์๋ก ๋๊ฒจ ์ค๋ณต๋ ํค๋ฅผ ์ด๋ป๊ฒ ํฉ์น ์ง ๋ฏธ๋ฆฌ ์ ํ ์ ์๋ค.
Map<String, String> everyone2 = new HashMap<>(family);
friends.forEach((k,v)->everyone2.merge(k,v,(movie1, movie2)->movie1+" & "+movie2));
๋๋ ์๋์ ๊ฐ์ด ์ด๊ธฐ๊ฐ์ ์ ํ๊ณ ๊ฐ์ ๊ฐฑ์ ํด๋๊ฐ ์๋ ์๋ค.
moviesToCount.merge(movieName, 1L, (k, v)->v+1L);
- ๋ด๋ถ ์๋ฃ๊ตฌ์กฐ์ ํน์ ๋ถ๋ถ๋ง ์ ๊ถ ๋์ ์ถ๊ฐ, ๊ฐฑ์ ์์ ์ ํ ์ ์๋ค.
- ๋๊ธฐํ๋ Hashtable์ ๋นํด ์ฝ๊ธฐ ์ฐ๊ธฐ ์ฐ์ฐ ์ฑ๋ฅ์ด ์๋ฑํ๋ค. (์ฐธ๊ณ ๋ก HashMap์ ๋น๋๊ธฐ๋ก ๋์)
-
์ฐ์ฐ์ข ๋ฅ
-
forEach ํค/๊ฐ ์์ ์ฃผ์ด์ง ์ก์ ์ ์คํ
-
redue ๋ชจ๋ ํค/๊ฐ ์์ ์ ๊ณต๋ ๋ฆฌ๋์ค ํจ์๋ฅผ ์ด์ฉํด ๊ฒฐ๊ณผ๋ก ํฉ์นจ
-
search ๋์ด ์๋ ๊ฐ์ ๋ฐํํ ๋๊น์ง ํค/๊ฐ์ ํจ์๋ฅผ ์ ์ฉ
-
-
์ฐ์ฐ๋ฐฉ๋ฒ
- ํค, ๊ฐ์ผ๋ก : forEach, reduce, search
- ํค๋ก : forEachKey, reduceKeys, searchKeys
- ๊ฐ์ผ๋ก : forEachValue, reduceValues, searchValues
- Map.Entry ๊ฐ์ฒด๋ก : forEachEntry, reduceEntries, searchEntries
์ ์ฐ์ฐ๋ค์ ConcurrentHashMap์ ์ํ๋ฅผ ์ ๊ทธ์ง ์๋๋ค. ์ด๋ค ์ฐ์ฐ์ ์ ๊ณตํ ํจ์๋ ์งํ๋๋ ๋์ ๋ฐ๋ ์ ์๋ ๊ฐ์ฒด, ๊ฐ, ์์ ๋ฑ์ ์์กดํ์ง ์์์ผ ํ๋ค.
์์ธ๋ฌ ์ฒซ๋ฒ์งธ ์ธ์๋ก ๋ณ๋ ฌ์ฑ ๊ธฐ์ค๊ฐ(threshold)์ ์ ํด์ค์ผ ํ๋๋ฐ, ๊ธฐ์ค๊ฐ์ด 1์ด๋ฉด ๋ณ๋ ฌ์ฑ์ ๊ทน๋ํํ๊ณ Long.MAX_VALUE์ด๋ฉด ํ ๊ฐ ์ค๋ ๋๋ก ์ฐ์ฐ์ ์คํํ๋ค.
ConcurrentHashMap<String, Long> map = new ConcurrentHashMap<>();
long parallelismThreshod = 1;
Optional<Long> maxValue = Optional.ofNullable(map.reduceValues(parallelismThreshod, Long::max));
ํ์์ ๊ธฐ๋ณธ๊ฐ ์ ์ฉ ์ฐ์ฐ์ ์ฌ์ฉํ์. (reduceValuesToInt, reduceKeysToLong ๋ฑ)
- mappingCount : long์ ๋ฐํํจ
- size : int๋ฅผ ๋ฐํ
concurrentHashMap ํฌ๊ธฐ๊ฐ int๊ฐ์ ๋์ด๊ฐ ๋๋ฅผ ๋๋นํ ์ ์๋ค.
โ
- keySet : ํค๊ฐ์ ์งํฉ์ผ๋ก ๋ณผ ์ ์๋ค. ์งํฉ/๋งต ๋ณ๊ฒฝ์ฌํญ์ด ์ํธ๊ฐ ์ ์ฉ๋๋ค. ๋จ, ์งํฉ์ ๊ฐ์ ์ถ๊ฐํ๋ ค๋ฉด keySet ์์ฑ์ ์ธ์๋ก ๊ธฐ๋ณธ๊ฐ์ ๋๊ฒจ์ฃผ์ด์ผ ํ๋ค.
- newKeySet : ์ ๋งต ๊ฐ์ฒด์ ์งํฉ๋ทฐ๋ฅผ ๋์์ ์์ฑํ๋ค. ๊ธฐ๋ณธ๊ฐ์ TRUE๋ก ์ง์ ํด์ค๋ค.
Set<String> set = map.keySet(0L);
System.out.println(map);
System.out.println(set);
set.add("BYE");
System.out.println(map);
System.out.println(set);
map.replace("A", 100L);
map.put("HELLO", 1000L);
System.out.println(map);
System.out.println(set);
keySet์ CollectinView๋ฅผ ์์ํ๋ keySetView๋ฅผ ๋ฐํํ๋ค.
-
CollectionView ๋ฉ์๋
- clear() size() isEmpty() iterator(), containse(), remove(), toArray(), toString(), containsAll(), removeAll(), retainAll()
-
keySetView ๋ฉ์๋
-
keySetView ์์ฑ์์์ ๋ํดํธ ๊ฐ์ ์ธ์๋ก ๋ฐ๋๋ค. ๋ง์ฝ ๊ฐ์ฒด ์์ฑ์ ๋ํดํธ ๊ฐ์ ์ ํด์ฃผ์ง ์์ผ๋ฉด ์๋์ ๊ฐ์ด ์์ธ๋ฅผ ๋ฐ์์ํจ๋ค.
-
public boolean add(K e) { V v; if ((v = value) == null) throw new UnsupportedOperationException(); return map.putVal(e, v, true) == null; }
-
System.out.println("#1 ==========================================");
ConcurrentHashMap.KeySetView<String, Long> set = map.keySet(0L);
System.out.println(map);
System.out.println(set);
System.out.println(set.getMappedValue());
System.out.println("#2 ==========================================");
ConcurrentHashMap.KeySetView<String, Long> kset = map.keySet();
System.out.println(kset.getMappedValue());
System.out.println("#3 ==========================================");
set.add("BYE");
System.out.println(map);
System.out.println(set);
System.out.println("#4 ==========================================");
map.replace("A", 100L);
map.put("HELLO", 1000L);
System.out.println(map);
System.out.println(set);
System.out.println("#5 ==========================================");
ConcurrentHashMap.KeySetView<String, Boolean> keySet = ConcurrentHashMap.newKeySet();
keySet.add("HELLO");
System.out.println(keySet);
System.out.println("#6 ==========================================");
ConcurrentHashMap.KeySetView<String, Boolean> keySet2 = ConcurrentHashMap.newKeySet(10);
keySet.add("HELLO");
System.out.println(keySet);
System.out.println(keySet.size());