item 46 incheol - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki
Effective Java 3e ์์ดํ 46๋ฅผ ์์ฝํ ๋ด์ฉ ์ ๋๋ค.
์คํธ๋ฆผ์ ๊ทธ์ ๋ ํ๋์ API๊ฐ ์๋, ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๊ธฐ์ดํ ํจ๋ฌ๋ค์์ด๋ค. ์คํธ๋ฆผ์ด ์ ๊ณตํ๋ ํํ๋ ฅ, ์๋, (์ํฉ์ ๋ฐ๋ผ์๋) ๋ณ๋ ฌ์ฑ์ ์ป์ผ๋ ค๋ฉด API๋ ๋งํ ๊ฒ๋ ์๊ณ ์ด ํจ๋ฌ๋ค์๊น์ง ํจ๊ป ๋ฐ์๋ค์ฌ์ผ ํ๋ค.
์คํธ๋ฆผ ํจ๋ฌ๋ค์์ ํต์ฌ์ ๊ณ์ฐ์ ์ผ๋ จ์ ๋ณํ์ผ๋ก ์ฌ๊ตฌ์ฑํ๋ ๋ถ๋ถ์ด๋ค. ์ด๋ ๊ฐ ๋ณํ ๋จ๊ณ๋ ๊ฐ๋ฅํ ํ ์ด์ ๋จ๊ณ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ ์ฒ๋ฆฌํ๋ ์์ ํจ์์ฌ์ผ ํ๋ค. ์์ ํจ์๋ ์ค์ง ์ ๋ ฅ๋ง์ด ๊ฒฐ๊ณผ์ ์ํฅ์ ์ฃผ๋ ํจ์๋ฅผ ๋งํ๋ค. ์ด๋ ๊ฒ ํ๋ ค๋ฉด (์ค๊ฐ ๋จ๊ณ๋ ์ข ๋จ ๋จ๊ณ๋ ) ์คํธ๋ฆผ ์ฐ์ฐ์ ๊ฑด๋ค๋ ํจ์ ๊ฐ์ฒด๋ ๋ชจ๋ ๋ถ์์ฉ์ด ์์ด์ผ ํ๋ค.
๋ค์์ ์ฃผ์์์ ์ข ์ข ๋ณผ ์ ์๋ ์คํธ๋ฆผ ์ฝ๋๋ก, ํ ์คํธ ํ์ผ์์ ๋จ์ด๋ณ ์๋ฅผ ์ธ์ด ๋น๋ํ๋ก ๋ง๋๋ ์ผ์ ํ๋ค.
Map<String, Long> freq = new HashMap<>();
try (Stream<String> words = new Scanner(file).tokens()) {
words.forEach(word -> {
freq.merge(word.toLowerCase(), 1L, Long::sum;
});
}
์ด๋ ์คํธ๋ฆผ ์ฝ๋๋ฅผ ๊ฐ์ฅํ ๋ฐ๋ณต์ ์ฝ๋๋ค. ์คํธ๋ฆผ API์ ์ด์ ์ ์ด๋ฆฌ์ง ๋ชปํ์๋ค. ์ด ์ฝ๋์ ๋ชจ๋ ์์ ์ด ์ข ๋จ ์ฐ์ฐ์ธ forEach์์ ์ผ์ด๋๋๋ฐ, ์ด๋ ์ธ๋ถ ์ํ(๋น๋ํ)๋ฅผ ์์ ํ๋ ๋๋ค๋ฅผ ์คํํ๋ฉด์ ๋ฌธ์ ๊ฐ ์๊ธด๋ค. forEach๊ฐ ๊ทธ์ ์คํธ๋ฆผ์ด ์ํํ ์ฐ์ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ฃผ๋ ์ผ ์ด์์ ํ๋ ๊ฒ์๋ณด๋ ๋์ ์ฝ๋์ผ ๊ฒ ๊ฐ์ ๋์๊ฐ ๋๋ค.
forEach ์ฐ์ฐ์ ์ข ๋จ ์ฐ์ฐ ์ค ๊ธฐ๋ฅ์ด ๊ฐ์ฅ ์ ๊ณ ๊ฐ์ฅ '๋' ์คํธ๋ฆผํ๋ค. ๋๋๊ณ ๋ฐ๋ณต์ ์ด๋ผ์ ๋ณ๋ ฌํํ ์๋ ์๋ค. forEach ์ฐ์ฐ์ ์คํธ๋ฆผ ๊ณ์ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ ๋๋ง ์ฌ์ฉํ๊ณ , ๊ณ์ฐํ๋ ๋ฐ๋ ์ฐ์ง ๋ง์.
์์ ์ฝ๋๋ ์๋์ ๊ฐ์ด ๊ฐ์ ๋ ์ ์๋ค.
Map<String, Long> freq;
try (Stream<String> words = new Scanner(file).tokens()) {
freq = words.
collection(groupingBy(String::toLowerCase, counting()));
}
์์ง๊ธฐ๊ฐ ์์ฑํ๋ ๊ฐ์ฒด๋ ์ผ๋ฐ์ ์ผ๋ก ์ปฌ๋ ์ ์ด๋ฉฐ, ๊ทธ๋์ "collector"๋ผ๋ ์ด๋ฆ์ ์ด๋ค.
์์ง๊ธฐ๋ฅผ ์ฌ์ฉํ๋ฉด ์คํธ๋ฆผ์ ์์๋ฅผ ์์ฝ๊ฒ ์ปฌ๋ ์ ์ผ๋ก ๋ชจ์ ์ ์๋ค.
List<String> topTen = freq.keySet().stream()
.sorted(comparing(freq::get).reversed())
.limit(10)
.collect(toList());
comparing ๋ฉ์๋๋ ํค ์ถ์ถ ํจ์๋ฅผ ๋ฐ๋ ๋น๊ต์ ์์ฑ ๋ฉ์๋๋ค.
์์ปจ๋ ๋ค์ํ ์์ ๊ฐ์ ์จ๋ฒ๋ค์ ๋ด์ ์คํธ๋ฆผ์ ๊ฐ์ง๊ณ , ์์ ๊ฐ์ ๊ทธ ์์ ๊ฐ์ ๋ฒ ์คํธ ์จ๋ฒ์ ์ฐ๊ด ์ง๊ณ ์ถ๋ค๊ณ ํด๋ณด์.
private static final Map<String, Operation> stringToEnum =
Stream.of(values()).collect(toMap(Object::toString, e -> e));
toMap ํํ๋ ์คํธ๋ฆผ์ ๊ฐ ์์๊ฐ ๊ณ ์ ํ ํค์ ๋งคํ๋์ด ์์ ๋ ์ ํฉํ๋ค. ์คํธ๋ฆผ ์์ ๋ค์๊ฐ ๊ฐ์ ํค๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ํ์ดํ๋ผ์ธ์ด IllegalStateException์ ๋์ง๋ฉฐ ์ข ๋ฃ๋ ๊ฒ์ด๋ค.
Map<Artist, Album> topHits = albums.collect(
toMap(Album::artist, a->a, maxBy(comparing(Album::sales))));
์์ ์ฝ๋๋ฅผ ๋ง๋ก ํ์ด๋ณด์๋ฉด "์จ๋ฒ ์คํธ๋ฆผ์ ๋งต์ผ๋ก ๋ฐ๊พธ๋๋ฐ, ์ด ๋งต์ ๊ฐ ์์ ๊ฐ์ ๊ทธ ์์ ๊ฐ์ ๋ฒ ์คํธ ์จ๋ฒ์ ์ง์ง์ ๊ฒ์ด๋ค"๋ ์ด์ผ๊ธฐ๋ค.
- groupingBy์ ์ฌ์ด๊ฒฉ์ธ partitioningBy๋ ์๋ค. ๋ถ๋ฅ ํจ์ ์๋ฆฌ์ ํ๋ ๋ํค๋(predicate)๋ฅผ ๋ฐ๊ณ ํค๊ฐ Boolean์ธ ๋งต์ ๋ฐํํ๋ค.
- Stream์ count ๋ฉ์๋๋ฅผ ์ง์ ์ฌ์ฉํ์ฌ ๊ฐ์ ๊ธฐ๋ฅ์ ์ํํ ์ ์์ผ๋ collect(counting()) ํํ๋ก ์ฌ์ฉํ ์ผ์ ์ ํ ์๋ค. Collections์๋ ์ด๋ฐ ์์ฑ์ ๋ฉ์๋๊ฐ 16๊ฐ๋ ๋ ์๋ค. ๊ทธ์ค 9๊ฐ๋ ์ด๋ฆ์ด summing, averaging, summarizing ์ผ๋ก ์์ํ๋ฉฐ, ๊ฐ๊ฐ int, long, double ์คํธ๋ฆผ์ฉ์ผ๋ก ํ๋์ฉ ์กด์ฌํ๋ค.
- minBy, maxBy๋ ์ธ์๋ก ๋ฐ์ ๋น๊ต์๋ฅผ ์ด์ฉํด ์คํธ๋ฆผ์์ ๊ฐ์ด ๊ฐ์ฅ ์์ ํน์ ๊ฐ์ฅ ํฐ ์์๋ฅผ ์ฐพ์ ๋ฐํํ๋ค.
- Collectors์ joining ๋ฉ์๋๋ CharSequence ์ธ์คํด์ค์ ์คํธ๋ฆผ์๋ง ์ ์ฉํ ์ ์๋ค. ์ด ๋ฉ์๋๋ ์ฐ๊ฒฐ ๋ถ์์ ๊ตฌ๋ถ๋ฌธ์๋ฅผ ์ฝ์ ํ๋๋ฐ, ์์ปจ๋ ๊ตฌ๋ถ๋ฌธ์๋ก ์ผํ(,)๋ฅผ ์ ๋ ฅํ๋ฉด CSV ํํ์ ๋ฌธ์์ด์ ๋ง๋ค์ด์ค๋ค.
์คํธ๋ฆผ ํ์ดํ๋ผ์ธ ํ๋ก๊ทธ๋๋ฐ์ ํต์ฌ์ ๋ถ์์ฉ ์๋ ํจ์ ๊ฐ์ฒด์ ์๋ค. ์คํธ๋ฆผ๋ฟ ์๋๋ผ ์คํธ๋ฆผ ๊ด๋ จ ๊ฐ์ฒด์ ๊ฑด๋ค์ง๋ ๋ชจ๋ ํจ์ ๊ฐ์ฒด๊ฐ ๋ถ์์ฉ์ด ์์ด์ผ ํ๋ค. ์ข ๋จ ์ฐ์ฐ ์ค forEach๋ ์คํธ๋ฆผ์ด ์ํํ ๊ณ์ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ ๋๋ง ์ด์ฉํด์ผ ํ๋ค. ๊ณ์ฐ ์์ฒด์๋ ์ด์ฉํ์ง ๋ง์. ์คํธ๋ฆผ์ ์ฌ๋ฐ๋ก ์ฌ์ฉํ๋ ค๋ฉด ์์ง๊ธฐ๋ฅผ ์ ์์๋ฌ์ผ ํ๋ค. ๊ฐ์ฅ ์ค์ํ ์์ง๊ธฐ ํฉํฐ๋ฆฌ๋ toList, toSet, toMap, groupingBy, joining์ด๋ค.