- 스트림 연산을 '파이프라인'이라고 한다.
- 스트림 파이프라인은
소스 스트림 - 중간 연산 - 종단 연산
의 세 단계로 나뉜다. - 스트림의 데이터 원소는 참조 타입과 또는 기본 타입 int, long, double 이다.
- 즉 byte, short, float, char, boolean은 지원하지 않는다.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
public class Anagrams {
public static void main(String[] args) throws FileNotFoundException {
File dictionary = new File("src/test/resources/dictionary.txt");
int minGroupSize = 3;
Map<String, Set<String>> groups = new HashMap<>();
try (Scanner scanner = new Scanner(dictionary)) {
while (scanner.hasNext()) {
String word = scanner.next();
groups.computeIfAbsent(alphabetize(word), __ -> 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 word) {
char[] alphabets = word.toCharArray();
Arrays.sort(alphabets);
return new String(alphabets);
}
}
- 애너그램(anargram)이란?
- 알파벳이 같고 순서가 다른 단어
- 예1) Everland <-> Lavender
- 예2) Heart <-> Earth
- 예3) Listen <-> Silent
- 예4) Woowa <-> Wawoo <-> Awowoo <-> Oowaw
dobbie hotie tohie zeus eusz uzes lisa alis lias asil
minGroupSize = 1;
4: [alis, asil, lias, lisa]
1: [dobbie]
2: [hotie, tohie]
3: [eusz, uzes, zeus]
Process finished with exit code 0
minGroupSize = 3;
4: [alis, asil, lias, lisa]
3: [eusz, uzes, zeus]
Process finished with exit code 0
import static java.util.stream.Collectors.groupingBy;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class Anagrams {
public static void main(String[] args) throws IOException {
Path dictionary = Paths.get("src/test/resources/dictionary.txt");
int minGroupSize = 3;
try (Stream<String> words = Files.lines(dictionary)) {
words.collect(
groupingBy(word -> word.chars().sorted()
.collect(StringBuilder::new,
(stringBuilder, c) -> stringBuilder.append((char) c),
StringBuilder::append).toString()))
.values().stream()
.filter(group -> group.size() >= minGroupSize)
.map(group -> group.size() + ": " + group)
.forEach(System.out::println);
}
}
}
- 스트림을 잘못 사용하면 이렇게 이해하기 어려운 코드가 된다.
String.chars()
?public IntStream chars()
import static java.util.stream.Collectors.groupingBy;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Stream;
public class Anagrams {
public static void main(String[] args) throws IOException {
Path dictionary = Paths.get("src/test/resources/dictionary.txt");
int minGroupSize = 3;
try (Stream<String> words = Files.lines(dictionary)) {
words.collect(groupingBy(Anagrams::alphabetize))
.values().stream()
.filter(group -> group.size() >= minGroupSize)
.forEach(System.out::println);
}
}
private static String alphabetize(String word) {
char[] alphabets = word.toCharArray();
Arrays.sort(alphabets);
return new String(alphabets);
}
}
- 람다에서는 타입 이름을 자주 생략하므로 매개변수 이름을 잘 지어야 스트림 파이프라인의 가독성이 유지된다.
- Helper 메서드를 적절히 활용하는 것은 반복문에서보다 스트림에서 그 중요성이 훨씬 크다.
- 스트림의 데이터 원소는 참조 타입과 또는 기본 타입 int, long, double 이다.
- 즉 byte, short, float, char, boolean은 지원하지 않는다.
- ➡️ 연산할 수 없다는 것은 아니고, 연산을 위한 메서드(예를 들면 sum)가 없어서 직접 만들어야 한다.
import org.junit.jupiter.api.Test;
class CharStreamTest {
@Test
public void test() {
"Hello world!".chars().forEach(System.out::println);
}
}
72
101
108
108
111
32
119
111
114
108
100
33
Process finished with exit code 0
- 스트림 파이프라인은 반복되는 계산을 함수 객체(람다 또는 메서드 참조)로 표현한다.
- 그러므로 주의해야 한다.
- 코드블럭은 되는데 함수객체는 안 되는 작업이 있다.
- 코드블럭은 지역변수를 수정할 수 있다. 함수 객체는 불가능하다.
- 사실상 final 변수만 읽을 수 있다.
- return, break, continue 등으로 반복의 흐름을 제어할 수 없다.
- 코드블럭은 지역변수를 수정할 수 있다. 함수 객체는 불가능하다.
for {
}
메서드 참조
System.out::println
람다
group -> group.size() >= minGroupSize
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
int sum = 0; // 외부 지역 변수
numbers.stream().forEach(n -> {
sum += n; // 컴파일 오류
});
System.out.println("Sum: " + sum);
컴파일 오류 메세지
Variable used in lambda expression should be final or effectively final
- 일련의 원소들을 일관되게 변환한다. (
map
) - 일련의 원소들을 필터링한다. (
filter
) - 일련의 원소들을 하나의 연산으로 결합한다. (
sum
,concat
,min
...) - 일련의 원소들을 컬렉션으로 묶는다. (
collect
) - 특정 조건을 만족하는 원소를 찾는다. (
anyMatch
)
-
파이프라인의 각 단계에서의 값에 동시에 접근하기 어려운 경우 스트림을 사용하지 않는 게 좋다.
- 한 단계를 통과하면 원래의 값을 읽기 때문
- 뭔소리임? -> 예제로 보자.
-
메르센 소수
- 형태가
$2^p-1$ 로 표현되는 소수 -
$p$ 가 소수일 때,$2^p-1$ 이 소수인 경우 메르센 소수라고 한다.
- 형태가
import static java.math.BigInteger.ONE;
import static java.math.BigInteger.TWO;
import java.math.BigInteger;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
class CharStreamTest {
@DisplayName("처음 20개의 메르센 소수를 출력한다.")
@Test
void test() {
primes().map(prime -> TWO.pow(prime.intValueExact()).subtract(ONE))
.filter(mersenne -> mersenne.isProbablePrime(50))
.limit(20)
.forEach(System.out::println);
}
Stream<BigInteger> primes() {
return Stream.iterate(TWO, BigInteger::nextProbablePrime);
}
}
3
7
31
127
8191
131071
524287
2147483647
2305843009213693951
618970019642690137449562111
162259276829213363391578010288127
170141183460469231731687303715884105727
6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151
531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127
10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087
1475979915214180235084898622737381736312066145333169775147771216478570297878078949377407337049389289382748507531496480477281264838760259191814463365330269540496961201113430156902396093989090226259326935025281409614983499388222831448598601834318536230923772641390209490231836446899608210795482963763094236630945410832793769905399982457186322944729636418890623372171723742105636440368218459649632948538696905872650486914434637457507280441823676813517852099348660847172579408422316678097670224011990280170474894487426924742108823536808485072502240519452587542875349976558572670229633962575212637477897785501552646522609988869914013540483809865681250419497686697771007
446087557183758429571151706402101809886208632412859901111991219963404685792820473369112545269003989026153245931124316702395758705693679364790903497461147071065254193353938124978226307947312410798874869040070279328428810311754844108094878252494866760969586998128982645877596028979171536962503068429617331702184750324583009171832104916050157628886606372145501702225925125224076829605427173573964812995250569412480720738476855293681666712844831190877620606786663862190240118570736831901886479225810414714078935386562497968178729127629594924411960961386713946279899275006954917139758796061223803393537381034666494402951052059047968693255388647930440925104186817009640171764133172418132836351
259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071
190797007524439073807468042969529173669356994749940177394741882673528979787005053706368049835514900244303495954950709725762186311224148828811920216904542206960744666169364221195289538436845390250168663932838805192055137154390912666527533007309292687539092257043362517857366624699975402375462954490293259233303137330643531556539739921926201438606439020075174723029056838272505051571967594608350063404495977660656269020823960825567012344189908927956646011998057988548630107637380993519826582389781888135705408653045219655801758081251164080554609057468028203308718724654081055323215860189611391296030471108443146745671967766308925858547271507311563765171008318248647110097614890313562856541784154881743146033909602737947385055355960331855614540900081456378659068370317267696980001187750995491090350108417050917991562167972281070161305972518044872048331306383715094854938415738549894606070722584737978176686422134354526989443028353644037187375385397838259511833166416134323695660367676897722287918773420968982326089026150031515424165462111337527431154890666327374921446276833564519776797633875503548665093914556482031482248883127023777039667707976559857333357013727342079099064400455741830654320379350833236245819348824064783585692924881021978332974949906122664421376034687815350484991
285542542228279613901563566102164008326164238644702889199247456602284400390600653875954571505539843239754513915896150297878399377056071435169747221107988791198200988477531339214282772016059009904586686254989084815735422480409022344297588352526004383890632616124076317387416881148592486188361873904175783145696016919574390765598280188599035578448591077683677175520434074287726578006266759615970759521327828555662781678385691581844436444812511562428136742490459363212810180276096088111401003377570363545725120924073646921576797146199387619296560302680261790118132925012323046444438622308877924609373773012481681672424493674474488537770155783006880852648161513067144814790288366664062257274665275787127374649231096375001170901890786263324619578795731425693805073056119677580338084333381987500902968831935913095269821311141322393356490178488728982288156282600813831296143663845945431144043753821542871277745606447858564159213328443580206422714694913091762716447041689678070096773590429808909616750452927258000843500344831628297089902728649981994387647234574276263729694848304750917174186181130688518792748622612293341368928056634384466646326572476167275660839105650528975713899320211121495795311427946254553305387067821067601768750977866100460014602138408448021225053689054793742003095722096732954750721718115531871310231057902608580607
Process finished with exit code 0
이때 각 메르센 소수 앞에 지수 p를 출력한다고 해보자.
import static java.math.BigInteger.ONE;
import static java.math.BigInteger.TWO;
import java.math.BigInteger;
import java.util.stream.Stream;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
class CharStreamTest {
@DisplayName("처음 20개의 메르센 소수를 출력한다.")
@Test
void test() {
primes().map(prime -> TWO.pow(prime.intValueExact()).subtract(ONE))
.filter(mersenne -> mersenne.isProbablePrime(50))
.limit(20)
.forEach(prime -> System.out.println(prime.bitLength() + ": " + prime));
}
Stream<BigInteger> primes() {
return Stream.iterate(TWO, BigInteger::nextProbablePrime);
}
}
2: 3
3: 7
5: 31
7: 127
13: 8191
17: 131071
19: 524287
31: 2147483647
61: 2305843009213693951
89: 618970019642690137449562111
107: 162259276829213363391578010288127
127: 170141183460469231731687303715884105727
521: 6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151
607: 531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127
1279: 10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087
2203: 1475979915214180235084898622737381736312066145333169775147771216478570297878078949377407337049389289382748507531496480477281264838760259191814463365330269540496961201113430156902396093989090226259326935025281409614983499388222831448598601834318536230923772641390209490231836446899608210795482963763094236630945410832793769905399982457186322944729636418890623372171723742105636440368218459649632948538696905872650486914434637457507280441823676813517852099348660847172579408422316678097670224011990280170474894487426924742108823536808485072502240519452587542875349976558572670229633962575212637477897785501552646522609988869914013540483809865681250419497686697771007
2281: 446087557183758429571151706402101809886208632412859901111991219963404685792820473369112545269003989026153245931124316702395758705693679364790903497461147071065254193353938124978226307947312410798874869040070279328428810311754844108094878252494866760969586998128982645877596028979171536962503068429617331702184750324583009171832104916050157628886606372145501702225925125224076829605427173573964812995250569412480720738476855293681666712844831190877620606786663862190240118570736831901886479225810414714078935386562497968178729127629594924411960961386713946279899275006954917139758796061223803393537381034666494402951052059047968693255388647930440925104186817009640171764133172418132836351
3217: 259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071
4253: 190797007524439073807468042969529173669356994749940177394741882673528979787005053706368049835514900244303495954950709725762186311224148828811920216904542206960744666169364221195289538436845390250168663932838805192055137154390912666527533007309292687539092257043362517857366624699975402375462954490293259233303137330643531556539739921926201438606439020075174723029056838272505051571967594608350063404495977660656269020823960825567012344189908927956646011998057988548630107637380993519826582389781888135705408653045219655801758081251164080554609057468028203308718724654081055323215860189611391296030471108443146745671967766308925858547271507311563765171008318248647110097614890313562856541784154881743146033909602737947385055355960331855614540900081456378659068370317267696980001187750995491090350108417050917991562167972281070161305972518044872048331306383715094854938415738549894606070722584737978176686422134354526989443028353644037187375385397838259511833166416134323695660367676897722287918773420968982326089026150031515424165462111337527431154890666327374921446276833564519776797633875503548665093914556482031482248883127023777039667707976559857333357013727342079099064400455741830654320379350833236245819348824064783585692924881021978332974949906122664421376034687815350484991
4423: 285542542228279613901563566102164008326164238644702889199247456602284400390600653875954571505539843239754513915896150297878399377056071435169747221107988791198200988477531339214282772016059009904586686254989084815735422480409022344297588352526004383890632616124076317387416881148592486188361873904175783145696016919574390765598280188599035578448591077683677175520434074287726578006266759615970759521327828555662781678385691581844436444812511562428136742490459363212810180276096088111401003377570363545725120924073646921576797146199387619296560302680261790118132925012323046444438622308877924609373773012481681672424493674474488537770155783006880852648161513067144814790288366664062257274665275787127374649231096375001170901890786263324619578795731425693805073056119677580338084333381987500902968831935913095269821311141322393356490178488728982288156282600813831296143663845945431144043753821542871277745606447858564159213328443580206422714694913091762716447041689678070096773590429808909616750452927258000843500344831628297089902728649981994387647234574276263729694848304750917174186181130688518792748622612293341368928056634384466646326572476167275660839105650528975713899320211121495795311427946254553305387067821067601768750977866100460014602138408448021225053689054793742003095722096732954750721718115531871310231057902608580607
Process finished with exit code 0
- 데카르트 곱이란 두 집합의 원소들로 만들 수 있는 가능한 모든 조합을 계산하는 문제다.
- 카드의 숫자(rank)와 무늬(suit)를 곱해 모든 카드 덱을 만드는 상황을 생각해보자.
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;
}
스트림으로 만들면 다음과 같다.
List<Card> newDeck() {
return Arrays.stream(Suit.values())
.flatMap(suit -> Stream.of(Rank.values())
.map(rank -> new Card(suit, rank)))
.toList();
}
- 반복문과 스트림을 둘 다 써보고 더 나은 쪽을 택하라.