item 45 junghyunlyoo - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki
์คํธ๋ฆผ API๋ ๋ค๋์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์์ (์์ฐจ์ ํน์ ๋ณ๋ ฌ์ )์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ํด ์๋ฐ 8์ ์ถ๊ฐ๋์๋ค.
์คํธ๋ฆผ API์ ํต์ฌ์ ๋๊ฐ์ง๋ค.
1. ์คํธ๋ฆผ(stream)์ ๋ฐ์ดํฐ ์์์ ์ ํ ํน์ ๋ฌดํ ์ํ์ค๋ฅผ ๋ปํ๋ค.
2. ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ(stream pipeline)์ ์ด ์์๋ค๋ก ์ํํ๋ ์ฐ์ฐ ๋จ๊ณ๋ฅผ ํํํ๋ ๊ฐ๋
์ด๋ค.
์คํธ๋ฆผ์ ์์๋ค์ ์ปฌ๋ ์ , ๋ฐฐ์ด, ํ์ผ, ์ ๊ทํํ์ ํจํด ๋งค์ฒ, ๋์ ์์ฑ๊ธฐ, ๋ค๋ฅธ ์คํธ๋ฆผ ๋ฑ ๋ค์ํ ๊ฒฝ๋ก๋ฅผ ํตํด ์กด์ฌํ ์ ์๋ค.
์คํธ๋ฆผ ์์ ๋ฐ์ดํฐ ์์๋ค์ ๊ฐ์ฒด ์ฐธ์กฐ๋ ๊ธฐ๋ณธ ํ์ ๊ฐ์ด๋ค.
๊ธฐ๋ณธ ํ์ ๊ฐ์ผ๋ก๋ int, long, double ์ธ๊ฐ์ง๋ฅผ ์ง์ํ๋ค.
IntStream intStream = IntStream.range(1, 5);
LongStream longStream = LongStream.range(1, 5);
DoubleStream doubleStream = DoubleStream.builder().add(1.2).build();
์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์์ค ์คํธ๋ฆผ์์ ์์ํด ์ข ๋จ ์ฐ์ฐ์ผ๋ก ๋๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ทธ ์ฌ์ด์ ํ๋ ์ด์์ ์ค๊ฐ ์ฐ์ฐ์ด ์์ ์ ์๋ค.
๊ฐ ์ค๊ฐ ์ฐ์ฐ์ ํน์ ๋ฐฉ์์ผ๋ก ์คํธ๋ฆผ์ ๋ณํํ๋ค.
์์ปจ๋ ๊ฐ ์์์ ํจ์๋ฅผ ์ ์ฉํ๊ฑฐ๋ ํน์ ์กฐ๊ฑด์ ๋ง์กฑํ์ง ๋ชปํ๋ ์์๋ฅผ ๊ฑธ๋ฌ๋ผ ์ ์๋ค.
์ค๊ฐ ์ฐ์ฐ๋ค์ ๋ชจ๋ ํ ์คํธ๋ฆผ์ ๋ค๋ฅธ ์คํธ๋ฆผ์ผ๋ก ๋ณํํ๋ค.
๋ณํ๋ ์คํธ๋ฆผ์ ์์ ํ์ ์ ๋ณํ ์ ์คํธ๋ฆผ์ ์์ ํ์ ๊ณผ ๊ฐ์ ์๋ ์๊ณ ๋ค๋ฅผ ์๋ ์๋ค.
์ข ๋จ ์ฐ์ฐ์ ๋ง์ง๋ง ์ค๊ฐ ์ฐ์ฐ์ด ๋ง๋ ์คํธ๋ฆผ์ ๋ง์ง๋ง ์ฐ์ฐ์ ์ ์ฉํ๋ค.
๋ณดํต ์์๋ฅผ ์ ๋ ฌํด์ ์ปฌ๋ ์ ์ ๋ด๊ฑฐ๋, ํน์ ์์๋ฅผ ์ ํํ๊ฑฐ๋, ๋ชจ๋ ์์๋ฅผ ์ถ๋ ฅํ๋ค.
์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์ง์ฐ ํ๊ฐ(lazy evaluation)๋๋ค.
์ง์ฐ ํ๊ฐ๋ฅผ '๊ฒ์ผ๋ฅธ ์ฐ์ฐ' ์ด๋ผ๊ณ ํํํ๊ธฐ๋ ํ๋ค.
ํ๊ฐ(์ค๊ฐ ์ฐ์ฐ)๋ ์ข ๋จ ์ฐ์ฐ์ด ํธ์ถ๋ ๋ ์ด๋ค์ง๋ฉฐ ์ข ๋จ ์ฐ์ฐ์ ์ฐ์ด์ง ์๋ ๋ฐ์ดํฐ ์์๋ ์ฌ์ค ์ค๊ฐ ์ฐ์ฐ์ ํฌํจํ ๋ชจ๋ ์ฐ์ฐ์ด ์ ์ฉ๋์ง ์๋๋ค.
์ด๋ฌํ ์ง์ฐ ํ๊ฐ๋ ๋ฌดํ ์คํธ๋ฆผ์ ๋ค๋ฃฐ ์ ์๊ฒ ํด์ฃผ๋ ์ค์ํ ์์์ด๋ค.
์ข ๋จ ์ฐ์ฐ์ด ์๋ ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์๋ฌด ์ผ๋ ํ์ง ์๋ ๋ช ๋ น์ด์ธ no-op๊ณผ ๊ฐ์ผ๋, ์ข ๋จ ์ฐ์ฐ์ ๋นผ๋จน๋ ์ผ์ด ์ ๋๋ก ์๋๋ก ํด์ผ๊ฒ ๋ค.
์คํธ๋ฆผ API๋ ๋ฉ์๋ ์ฐ์๋ฅผ ์ง์ํ๋ Fluent API๋ค.
์ฆ, ํ์ดํ๋ผ์ธ ํ๋๋ฅผ ๊ตฌ์ฑํ๋ ํธ์ถ๋ค์ ์ฐ๊ฒฐํ์ฌ ๋จ ํ๋์ ํํ์์ผ๋ก ์์ฑํ ์ ์๋ค.
ํ์ดํ๋ผ์ธ ์ฌ๋ฌ ๊ฐ๋ฅผ ์ฐ๊ฒฐํด ํํ์ ํ๋๋ก ๋ง๋ค ์๋ ์๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์์ฐจ์ ์ผ๋ก ์ํ๋๋ค.
ํ์ดํ๋ผ์ธ์ ๋ณ๋ ฌ๋ก ์คํํ๋ ค๋ฉด ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ๋ ์คํธ๋ฆผ ์ค ํ๋์์ parallel ๋ฉ์๋๋ฅผ ํธ์ถํด์ฃผ๊ธฐ๋ง ํ๋ฉด ๋๋, ํจ๊ณผ๋ฅผ ๋ณผ ์ ์๋ ์ํฉ์ ๋ง์ง ์๋ค. (item 48)
์คํธ๋ฆผ API๋ ๋ค์ํ ๊ณ์ฐ์ ํ์ฉ๋ ์ ์๋ค.
ํ์ง๋ง '์' ์ฌ์ฉํด์ผ ํ๋ค. ์๋ชป ์ฌ์ฉํ๋ฉด ์ฝ๊ธฐ ์ด๋ ต๊ณ ์ ์ง๋ณด์๋ ํ๋ค์ด์ง๋ค.
์คํธ๋ฆผ์ ์ธ์ ์จ์ผ ํ๋์ง๋ฅผ ๊ท์ ํ๋ ํ์คํ ๊ท์น์ ์์ง๋ง ์ฐธ๊ณ ํด๋ณผ๋งํ ๋ ธํ์ฐ๋ ์๋ค.
๋ค์ ์ฝ๋๋ฅผ ๋ณด์. ์ด ํ๋ก๊ทธ๋จ์ ์ฌ์ ํ์ผ์์ ๋จ์ด๋ฅผ ์ฝ์ด ์ฌ์ฉ์๊ฐ ์ง์ ํ ๋ฌธํฑ๊ฐ๋ณด๋ค ์์ ์๊ฐ ๋ง์ ์๋๊ทธ๋จ(anagram) ๊ทธ๋ฃน์ ์ถ๋ ฅํ๋ค.
์๋๊ทธ๋จ์ด๋ ์ฒ ์๋ฅผ ๊ตฌ์ฑํ๋ ์ํ๋ฒณ์ด ๊ฐ๊ณ ์์๋ง ๋ค๋ฅธ ๋จ์ด๋ฅผ ๋ปํ๋ค.
์ด ํ๋ก๊ทธ๋จ์ ์ฌ์ฉ์๊ฐ ๋ช ์ํ ์ฌ์ ํ์ผ์์ ๊ฐ ๋จ์ด๋ฅผ ์ฝ์ด ๋งต์ ์ ์ฅํ๋ค.
๋งต์ ํค๋ ๊ทธ ๋จ์ด๋ฅผ ๊ตฌ์ฑํ๋ ์ฒ ์๋ค์ ์ํ๋ฒณ์์ผ๋ก ์ ๋ ฌํ ๊ฐ์ด๋ค.
์ฆ 'staple'์ ํค๋ 'aelpst'๊ฐ ๋๊ณ 'petals'์ ํค๋ 'aelpst'๊ฐ ๋๋ค.
๋ฐ๋ผ์ ๋ ๋จ์ด๋ ์๋๊ทธ๋จ์ด๊ณ ์๋๊ทธ๋จ๋ผ๋ฆฌ๋ ๊ฐ์ ํค๋ฅผ ๊ณต์ ํ๋ค.
๋งต์ ๊ฐ์ ๊ฐ์ ํค๋ฅผ ๊ณต์ ํ ๋จ์ด๋ค์ ๋ด์ ์งํฉ์ด๋ค.
์ฌ์ ํ๋๋ฅผ ๋ชจ๋ ์ฒ๋ฆฌํ๊ณ ๋๋ฉด ๊ฐ ์งํฉ์ ์ฌ์ ์ ๋ฑ์ฌ๋ ์๋๊ทธ๋จ๋ค์ ๋ชจ๋ ๋ด์ ์ํ๊ฐ ๋๋ค.
๋ง์ง๋ง์ผ๋ก ์ด ํ๋ก๊ทธ๋จ์ ๋งต์ values()๋ก ์๋๊ทธ๋จ ์งํฉ๋ค์ ์ป์ด ์์ ์๊ฐ ๋ฌธํฑ๊ฐ๋ณด๋ค ๋ง์ ์งํฉ๋ค์ ์ถ๋ ฅํ๋ค.
public class IterativeAnagrams {
public static void main(String[] args) throws IOException {
File dictionary = new File(args[0]);
int minGroupSize = Integer.parseInt(args[1]);
Map<String, Set<String>> groups = new HashMap<>();
try (Scanner s = new Scanner(dictionary)) {
while (s.hasNext()) {
String word = s.next();
groups.computeIfAbsent(alphabetize(word),
(unused) -> new TreeSet<>()).add(word);
}
}
for (Set<String> group : groups.values())
if (group.size() >= minGroupSize)
System.out.println(group.size() + ": " + group);
}
private static String alphabetize(String s) {
char[] a = s.toCharArray();
Arrays.sort(a);
return new String(a);
}
}
์ด ํ๋ก๊ทธ๋จ์ ์ฒซ ๋ฒ์งธ ๋จ๊ณ์ ์ฃผ๋ชฉํ์.
๋งต์ ๊ฐ ๋จ์ด๋ฅผ ์ฝ์ ํ ๋ ์๋ฐ 8์์ ์ถ๊ฐ๋ computeIfAbsent()๋ฅผ ์ฌ์ฉํ๋ค.
์ด ๋ฉ์๋๋ ๋งต ์์ ํค๊ฐ ์๋์ง ์ฐพ์ ๋ค์, ์์ผ๋ฉด ๋จ์ํ ๊ทธ ํค์ ๋งคํ๋ ๊ฐ์ ๋ฐํํ๋ค.
ํค๊ฐ ์์ผ๋ฉด ๊ฑด๋ค์ง ํจ์ ๊ฐ์ฒด๋ฅผ ํค์ ์ ์ฉํ์ฌ ๊ฐ์ ๊ณ์ฐํด๋ธ ๋ค์ ๊ทธ ํค์ ๊ฐ์ ๋งคํํด๋๊ณ , ๊ณ์ฐ๋ ๊ฐ์ ๋ฐํํ๋ค.
์ด์ฒ๋ผ computeIfAbsent๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ ํค์ ๋ค์์ ๊ฐ์ ๋งคํํ๋ ๋งต์ ์ฝ๊ฒ ๊ตฌํํ ์ ์๋ค.
์ด์ ๋ค์ ํ๋ก๊ทธ๋จ์ ์ดํด๋ณด์.
IterativeAnagrams์ ๊ฐ์ ์ผ์ ํ์ง๋ง ์คํธ๋ฆผ์ ๊ณผํ๊ฒ ํ์ฉํ๋ค.
์ฌ์ ํ์ผ์ ์ฌ๋ ๋ถ๋ถ๋ง ์ ์ธํ๋ฉด ํ๋ก๊ทธ๋จ ์ ์ฒด๊ฐ ๋จ ํ๋์ ํํ์์ผ๋ก ์ฒ๋ฆฌ๋๋ค.
์ฌ์ ์ ์ฌ๋ ์์ ์ ๋ถ๋ฆฌํ ์ด์ ๋ ๊ทธ์ try-with-resources ๋ฌธ์ ์ฌ์ฉํด ์ฌ์ ํ์ผ์ ์ ๋๋ก ๋ซ๊ธฐ ์ํด์๋ค.
public class StreamAnagrams {
public static void main(String[] args) throws IOException {
Path dictionary = Paths.get(args[0]);
int minGroupSize = Integer.parseInt(args[1]);
try (Stream<String> words = Files.lines(dictionary)) {
words.collect(
groupingBy(word -> word.chars().sorted()
.collect(StringBuilder::new,
(sb, c) -> sb.append((char) c),
StringBuilder::append).toString()))
.values().stream()
.filter(group -> group.size() >= minGroupSize)
.map(group -> group.size() + ": " + group)
.forEach(System.out::println);
}
}
}
์ดํดํ๊ธฐ ํ๋ ์ฝ๋๋ค.... ์งง์ง๋ง ์ฝ๊ธฐ ์ด๋ ต๋ค. ํนํ ์คํธ๋ฆผ์ ์ต์ํ์ง ์์ ํ๋ก๊ทธ๋๋จธ๋ผ๋ฉด ๋์ฑ ๊ทธ๋ ๋ค.
์ด์ฒ๋ผ ์คํธ๋ฆผ์ ๊ณผ์ฉํ๋ฉด ํ๋ก๊ทธ๋จ ์ ์ง๋ณด์๊ฐ ํ๋ค์ด์ง๋ค.
๋คํํ ์ ์ถฉ ์ง์ ์ด ์๋ค. ์๋ ํ๋ก๊ทธ๋จ๋ ์ ๋ ํ๋ก๊ทธ๋จ๊ณผ ๊ธฐ๋ฅ์ ๊ฐ๋ค.
ํ์ง๋ง ์คํธ๋ฆผ์ ์ ๋นํ ์ฌ์ฉํ๊ณ ๊ทธ ๊ฒฐ๊ณผ ์ฝ๋์ ์๊ณผ ๊ฐ๋ ์ฑ ๋ชจ๋๋ฅผ ์ป์๋ค.
public class HybridAnagrams {
public static void main(String[] args) throws IOException {
Path dictionary = Paths.get(args[0]);
int minGroupSize = Integer.parseInt(args[1]);
try (Stream<String> words = Files.lines(dictionary)) {
words.collect(groupingBy(word -> alphabetize(word)))
.values().stream()
.filter(group -> group.size() >= minGroupSize)
.forEach(g -> System.out.println(g.size() + ": " + g));
}
}
private static String alphabetize(String s) {
char[] a = s.toCharArray();
Arrays.sort(a);
return new String(a);
}
}
try-with-resources์์ ์ฌ์ ํ์ผ์ ์ด๊ณ , ํ์ผ์ ๋ชจ๋ ๋ผ์ธ์ผ๋ก ๊ตฌ์ฑ๋ ์คํธ๋ฆผ์ ์ป๋๋ค.
์คํธ๋ฆผ ๋ณ์์ ์ด๋ฆ์ words๋ก ์ง์ด ์คํธ๋ฆผ ์์ ๊ฐ ์์๊ฐ ๋จ์ด(words)์์ ๋ช ํํ ํ๋ค.
์ด ์คํธ๋ฆผ์ ํ์ดํ๋ผ์ธ์๋ ์ค๊ฐ ์ฐ์ฐ์ ์์ผ๋ฉฐ, ์ข ๋จ ์ฐ์ฐ์์๋ ๋ชจ๋ ๋จ์ด๋ฅผ ์์งํด ๋งต์ผ๋ก ๋ชจ์๋ค.
์ด ๋งต์ ๋จ์ด๋ค์ ์๋๊ทธ๋จ๋ผ๋ฆฌ ๋ฌถ์ด๋์ ๊ฒ์ด๋ค. (item 46)
(์์ ๋ ํ๋ก๊ทธ๋จ์ด ์์ฑํ ๋งต๊ณผ ์ค์ง์ ์ผ๋ก ๊ฐ๋ค)
๊ทธ๋ค์ ์ด ๋งต์ values๊ฐ ๋ฐํํ ๊ฐ์ผ๋ก๋ถํฐ ์๋ก์ด Stream<List> ์คํธ๋ฆผ์ ์ฐ๋ค.
์ด ์คํธ๋ฆผ์ ์์๋ ๋ฌผ๋ก ์๋๊ทธ๋จ ๋ฆฌ์คํธ๋ค.
๊ทธ ๋ฆฌ์คํธ๋ค ์ค ์์๊ฐ minGroupSize๋ณด๋ค ์ ์ ๊ฒ์ ํํฐ๋ง๋ผ ๋ฌด์๋๋ค.
๋ง์ง๋ง์ผ๋ก ์ข ๋จ ์ฐ์ฐ์ธ forEach๋ ์ด์๋จ์ ๋ฆฌ์คํธ๋ฅผ ์ถ๋ ฅํ๋ค.
๋๋ค ๋งค๊ฐ๋ณ์์ ์ด๋ฆ์ ์ฃผ์ํด์ ์ ํด์ผ ํ๋ค.
HybridAnagrams์์์ ๋งค๊ฐ๋ณ์ g๋ ์ฌ์ค group์ด๋ผ๊ณ ํ๋๊ฒ ์ข๋ค.
ํ์ง๋ง ์ฑ
์ ์ง๋ฉด ํญ์ด ๋ถ์กฑํด ์งง๊ฒ ์ค์๋ค.
๋๋ค์์๋ ํ์
์ด๋ฆ์ ์์ฃผ ์๋ตํ๋ฏ๋ก ๋งค๊ฐ๋ณ์ ์ด๋ฆ์ ์ ์ง์ด์ผ ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ๊ฐ๋
์ฑ์ด ์ ์ง๋๋ค.
ํํธ, ๋จ์ด์ ์ฒ ์๋ฅผ ์ํ๋ฒณ์์ผ๋ก ์ ๋ ฌํ๋ ์ผ์ ๋ณ๋ ๋ฉ์๋์ธ alphabetize์์ ์ํํ๋ค.
์ฐ์ฐ์ ์ ์ ํ ์ด๋ฆ์ ์ง์ด์ฃผ๊ณ ์ธ๋ถ ๊ตฌํ์ ์ฃผ ํ๋ก๊ทธ๋จ ๋ก์ง ๋ฐ์ผ๋ก ๋นผ๋ด ์ ์ฒด์ ์ธ ๊ฐ๋
์ฑ์ ๋์ธ ๊ฒ์ด๋ค.
์ด์ฒ๋ผ ๋์ฐ๋ฏธ ๋ฉ์๋๋ฅผ ์ ์ ํ ํ์ฉํ๋ ์ผ์ ์ค์์ฑ์ ์ผ๋ฐ ๋ฐ๋ณต ์ฝ๋์์๋ณด๋ค๋ ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์์ ํจ์ฌ ํฌ๋ค.
์๋ํ๋ฉด ํ์ดํ๋ผ์ธ์์๋ ํ์
์ ๋ณด๊ฐ ๋ช
์๋์ง ์๊ฑฐ๋ ์์ ๋ณ์๋ฅผ ์์ฃผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค.
alphabetize()๋ ์คํธ๋ฆผ์ ์ฌ์ฉํด ๋ค๋ฅด๊ฒ ๊ตฌํํ ์ ์๋ค.
ํ์ง๋ง ๋ช ํ์ฑ์ด ๋จ์ด์ง๊ณ ์๋ชป ๊ตฌํํ ๊ฐ๋ฅ์ฑ์ด ์ปค์ง ์๋ ์๋ค. ์ฌ์ง์ด ๋๋ ค์ง ์๋ ์๋ค.
์๋ฐ๊ฐ ๊ธฐ๋ณธ ํ์ ์ธ char์ฉ ์คํธ๋ฆผ์ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
์๋ฐ๊ฐ char ์คํธ๋ฆผ์ ์ง์ํ์ด์ผ ํ๋ค๋ ๋ป์ ์๋๋ค. ๊ทธ๋ ๊ฒ ํ๋ ๊ฑด ๋ถ๊ฐ๋ฅํ๋ค!
์๋๋ char ๊ฐ๋ค์ ์คํธ๋ฆผ์ผ๋ก ์ฒ๋ฆฌํ๋ ์ฝ๋๋ค.
"Hello world!".chars().forEach(System.out::print);
"Hello world!" ๋ฅผ ์ถ๋ ฅํ๋ฆฌ๋ผ ๊ธฐ๋ํ๊ฒ ์ง๋ง, 72101108~~~~~~033 ์ ์ถ๋ ฅํ๋ค.
์๋ํ๋ฉด "Hello world!".chars()๊ฐ ๋ฐํํ๋ ์คํธ๋ฆผ์ ์์๋ char๊ฐ ์๋ int์ด๊ธฐ ๋๋ฌธ์ด๋ค.
๋ฐ๋ผ์ ์ ์๊ฐ์ ์ถ๋ ฅํ๋ print ๋ฉ์๋๊ฐ ํธ์ถ๋ ๊ฒ์ด๋ค.
์ด์ฒ๋ผ ์ด๋ฆ์ด chars์ธ๋ฐ int ์คํธ๋ฆผ์ ๋ฐํํ๋ฉด ํท๊ฐ๋ฆด ์ ์๋ค.
์ฌ๋ฐ๋ฅธ print ๋ฉ์๋๋ฅผ ํธ์ถํ๊ฒ ํ๋ ค๋ฉด ๋ค์์ฒ๋ผ ํ๋ณํ์ ๋ช ์์ ์ผ๋ก ํด์ผ ํ๋ค.
"Hello world!".chars().forEach(x -> System.out::print((char) x));
char ๊ฐ๋ค์ ์ฒ๋ฆฌํ ๋๋ ์คํธ๋ฆผ์ ์ผ๊ฐ๋ ํธ์ด ๋ซ๊ฒ ๋ค
ํํธ ์คํธ๋ฆผ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ด๋ ค์ด ์ผ๋ ์๋ค.
์๋ฅผ ๋ค์ด, ํ ๋ฐ์ดํฐ๊ฐ ํ์ดํ๋ผ์ธ์ ์ฌ๋ฌ ๋จ๊ณ(stage)๋ฅผ ํต๊ณผํ ๋ ์ด ๋ฐ์ดํฐ์ ๊ฐ ๋จ๊ณ์์์ ๊ฐ๋ค์ ๋์์ ์ ๊ทผ์ด ํ์ํ ๊ฒฝ์ฐ๋ฅผ ๋ค ์ ์๋ค.
์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์ผ๋จ ํ ๊ฐ์ ๋ค๋ฅธ ๊ฐ์ ๋งคํํ๊ณ ๋๋ฉด ์๋์ ๊ฐ์ ์์ด๋ฒ๋ฆฐ๋ค.
์๋ ๊ฐ๊ณผ ์๋ก์ด ๊ฐ์ ์์ ์ ์ฅํ๋ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด ๋งคํํ์ฌ ์ฐํํ ์๋ ์์ง๋ง ๊ทธ๋ฆฌ ์ข์ ๋ฐฉ๋ฒ์ ์๋๋ค.
๋งคํ ๊ฐ์ฒด๊ฐ ํ์ํ ๋จ๊ณ๊ฐ ์ฌ๋ฌ ๊ณณ์ด๋ผ๋ฉด ํนํ ๋ ๊ทธ๋ ๋ค
์ด๋ฐ ๋งคํ์ ํตํ ์ฐํํ๋ ๋ฐฉ์์ ์ฝ๋ ์๋ ๋ง๊ณ ์ง์ ๋ถํ๊ธฐ ๋๋ฌธ์ ์คํธ๋ฆผ์ ์ฐ๋ ์ฃผ๋ชฉ์ ์์ ์์ ํ ๋ฒ์ด๋๋ค.
๊ฐ๋ฅํ ๊ฒฝ์ฐ๋ผ๋ฉด, ์ ๋จ๊ณ์ ๊ฐ์ด ํ์ํ ๋ ๋งคํ์ ๊ฑฐ๊พธ๋ก ์ํํ๋ ๋ฐฉ๋ฒ์ด ๋์ ๊ฒ์ด๋ค.
'๋งคํ์ ๊ฑฐ๊พธ๋ก ์ํํ๋ ๋ฐฉ๋ฒ'์ ์๋ฅผ ๋ค์ด ๊ตฌ์ฒดํ ํด๋ณด์.
์ฒ์ 20๊ฐ์ ๋ฉ๋ฅด์ผ ์์๋ฅผ ์ถ๋ ฅํ๋ ํ๋ก๊ทธ๋จ์ ์์ฑํด๋ณด์.
๋ฉ๋ฅด์ผ ์๋ 2^p - 1 ํํ์ ์๋ค.
์ฌ๊ธฐ์ p๊ฐ ์์์ด๋ฉด ํด๋น ๋ฉ๋ฅด์ผ ์๋ ์์์ผ ์ ์๋๋ฐ,
์ด๋์ ์๋ฅผ ๋ฉ๋ฅด์ผ ์์๋ผ ํ๋ค.
์ด ํ์ดํ๋ผ์ธ์ ์ฒซ ์คํธ๋ฆผ์ผ๋ก๋ ๋ชจ๋ ์์๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ค.
๋ค์ ์ฝ๋๋ (๋ฌดํ) ์คํธ๋ฆผ์ ๋ฐํํ๋ ๋ฉ์๋๋ค.
static Stream<BigInteger> primes() {
return Stream.iterate(TWO, BigInteger::nextProbablePrime);
}
๋ฉ์๋ ์ด๋ฆ primes๋ ์คํธ๋ฆผ์ ์์๊ฐ ์์์์ ๋งํด์ค๋ค.
์คํธ๋ฆผ์ ๋ฐํํ๋ ๋ฉ์๋ ์ด๋ฆ์ ์ด์ฒ๋ผ ์์์ ์ ์ฒด๋ฅผ ์๋ ค์ฃผ๋ ๋ณต์ ๋ช
์ฌ๋ก ์ฐ๊ธฐ๋ฅผ ๊ฐ๋ ฅํ ์ถ์ฒํ๋ค.
์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ๊ฐ๋
์ฑ์ด ํฌ๊ฒ ์ข์์ง๋ค.
์ด ๋ฉ์๋๊ฐ ์ด์ฉํ๋ Stream.iterate๋ผ๋ ์ ์ ํฉํฐ๋ฆฌ๋ ๋งค๊ฐ๋ณ์๋ฅผ 2๊ฐ ๋ฐ๋๋ค.
์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ ์คํธ๋ฆผ์ ์ฒซ ๋ฒ์งธ ์์์ด๊ณ ๋ ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ ์คํธ๋ฆผ์์ ๋ค์ ์์๋ฅผ ์์ฑํด์ฃผ๋ ํจ์๋ค.
์ด์ ์ฒ์ 20๊ฐ์ ๋ฉ๋ฅด์ผ ์์๋ฅผ ์ถ๋ ฅํ๋ ํ๋ก๊ทธ๋จ์ ๋ณด์.
public static void main(String[] args) {
primes().map(p -> TWO.pow(p.intValueExact()).subtract(ONE))
.filter(mersenne -> mersenne.isProbablePrime(50))
.limit(20)
.forEach(System.out::println);
}
์ด ์ฝ๋๋ ์์์ ์ค๋ช ์ ์ ํํ๊ฒ ๊ตฌํํ๋ค.
์์๋ค์ ์ฌ์ฉํด ๋ฉ๋ฅด์ผ ์๋ฅผ ๊ณ์ฐํ๊ณ , ๊ฒฐ๊ด๊ฐ์ด ์์์ธ ๊ฒฝ์ฐ๋ง ๋จ๊ธด ๋ค์ (๋งค์ง๋๋ฒ 50์ ์์์ฑ ๊ฒ์ฌ๊ฐ true๋ฅผ ๋ฐํํ ํ๋ฅ ์ ์ ์ดํ๋ค)
๊ฒฐ๊ณผ ์คํธ๋ฆผ์ ์์ ์๋ฅผ 20๊ฐ๋ก ์ ํํด๋๊ณ ์์ ์ด ๋๋๋ฉด ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ค.
์ด์ ์ฐ๋ฆฌ๊ฐ ๊ฐ ๋ฉ๋ฅด์ผ ์์์ ์์ ์ง์(p)๋ฅผ ์ถ๋ ฅํ๊ธธ ์ํ๋ค๊ณ ํด๋ณด์.
์ด ๊ฐ์ ์ด๊ธฐ ์คํธ๋ฆผ์๋ง ๋ํ๋๋ฏ๋ก ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ ์ข ๋จ ์ฐ์ฐ์์๋ ์ ๊ทผํ ์ ์๋ค.
ํ์ง๋ง ๋คํํ ์ฒซ ๋ฒ์งธ ์ค๊ฐ ์ฐ์ฐ์์ ์ํํ ๋งคํ์ ๊ฑฐ๊พธ๋ก ์ํํด ๋ฉ๋ฅด์ผ ์์ ์ง์๋ฅผ ์ฝ๊ฒ ๊ณ์ฐํ ์ ์๋ค.
๋จ์ํ ์ซ์๋ฅผ ์ด์ง์๋ก ํํํ ๋ค์ ๋ช ๋นํธ์ธ์ง๋ฅผ ์ธ๋ฉด ํด๋น ์ซ์์ ์ง์๋ฅผ ์ป์ ์ ์์ผ๋ฏ๋ก, ์ข ๋จ ์ฐ์ฐ์ ๋ค์์ฒ๋ผ ์์ฑํ๋ฉด ๋๋ค.
.forEach(mp -> System.out.println(mp.bitLength() + ": " + mp));
์คํธ๋ฆผ๊ณผ ๋ฐ๋ณต ์ค ์ด๋ ์ชฝ์ ์จ์ผ ํ ์ง ๋ฐ๋ก ์๊ธฐ ์ด๋ ค์ด ์์ ๋ ๋ง๋ค.
์นด๋ ๋ฑ์ ์ด๊ธฐํํ๋ ์์ ์ ์๊ฐํด๋ณด์.
์นด๋๋ ์ซ์(rank)์ ๋ฌด๋ฌ(suit)๋ฅผ ๋ฌถ์ ๋ถ๋ณ ๊ฐ ํด๋์ค์ด๊ณ , ์ซ์์ ๋ฌด๋ฌ๋ ๋ชจ๋ ์ด๊ฑฐ ํ์ ์ด๋ผ ํ์.
์ด ์์ ์ ๋ ์งํฉ์ ์์๋ค๋ก ๋ง๋ค ์ ์๋ ๊ฐ๋ฅํ ๋ชจ๋ ์กฐํฉ์ ๊ณ์ฐํ๋ ๋ฌธ์ ๋ค.
์ํ์๋ค์ ์ด๋ฅผ ๋ ์งํฉ์ ๋ฐ์นด๋ฅดํธ ๊ณฑ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
๋ค์์ for-each ๋ฐ๋ณต๋ฌธ์ ์ค์ฒฉํด์ ๊ตฌํํ ์ฝ๋๋ก, ์คํธ๋ฆผ์ ์ต์ํ์ง ์์ ์ฌ๋์๊ฒ ์น์ํ ๋ฐฉ์์ด๋ค.
private static List<Card> newDeck() {
List<Card> result = new ArrayList<>();
for (Suit suit : Suit.values())
for (Rank rank : Rank.values())
result.add(new Card(suit, rank));
return result;
}
๋ค์์ ์คํธ๋ฆผ์ผ๋ก ๊ตฌํํ ์ฝ๋๋ค.
์ค๊ฐ ์ฐ์ฐ์ผ๋ก ์ฌ์ฉํ flatMap์ ์คํธ๋ฆผ์ ์์ ๊ฐ๊ฐ์ ํ๋์ ์คํธ๋ฆผ์ผ๋ก ๋งคํํ ๋ค์ ๊ทธ ์คํธ๋ฆผ๋ค์ ๋ค์ ํ๋์ ์คํธ๋ฆผ์ผ๋ก ํฉ์น๋ค.
์ด๋ฅผ ํํํ(flattening)๋ผ๊ณ ๋ ํ๋ค. ์ด ๊ตฌํ์์๋ ์ค์ฒฉ๋ ๋๋ค๋ฅผ ์ฌ์ฉํ์์ ์ฃผ์ํ์.
private static List<Card> newDeck() {
return Stream.of(Suit.values())
.flatMap(suit ->
Stream.of(Rank.values())
.map(rank -> new Card(suit, rank)))
.collect(toList());
}
์ด๋ ๋ฐฉ๋ฒ์ด ์ข์๊น? ๊ฐ์ธ ์ทจํฅ๊ณผ ํ๋ก๊ทธ๋๋ฐ ํ๊ฒฝ์ ๋ฌธ์ ๋ค.
for-each๋ฅผ ์ฌ์ฉํ ๋ฐฉ์์ ๋ ๋จ์ํ๊ณ ์์ฐ์ค๋ฌ์ ๋ณด์ธ๋ค.
์คํธ๋ฆผ๊ณผ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ต์ํ ํ๋ก๊ทธ๋๋จธ๋ผ๋ฉด ์คํธ๋ฆผ ๋ฐฉ์์ด ์กฐ๊ธ ๋ ๋ช ํํ๊ณ ์ฌ์ธ ๊ฒ์ด๋ค.
(์ด๋ค ๋ฐฉ์์ด ๋ง์ ์ง ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด ์ฒซ ๋ฒ์งธ ๋ฐฉ์์ ์ฐ๋๊ฒ ๋ ์์ ํ ๊ฒ์ด๋ค!)