์คํธ๋ฆผ์ด๋ ์๋ฐ 8๋ถํฐ ๋ค๋์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์์ (์์ฐจ/๋ณ๋ ฌ)์ ๋๊ณ ์ ๋์จ API์ด๋ฉฐ, ๋ ๊ฐ์ง ํต์ฌ์ ์ธ ์ถ์ ๊ฐ๋ ์ ์ ๊ณตํ๋ค.
์คํธ๋ฆผ
์ ์ํ๋ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํ๊ธฐ ์ํด ํ์ดํ๋ผ์ธ์ผ๋ก ์ฐ๊ฒฐ๋ ์ ์๋ ๋ค์ํ ๋ฉ์๋๋ฅผ ์ง์ํ๋ ๊ฐ์ฒด ์ํ์ค์ด๋ค. ๋ฐ์ดํฐ์ ํ๋ฆ, ์ฆ ์คํธ๋ฆผ์ด ํ๋ฌ๊ฐ๋ ๊ณผ์ ์์ ๋ฐ์ดํฐ๊ฐ ์์ฐจ์ ์ผ๋ก ํ๋์ฉ ์ฌ์ฉ๋๊ณ ์ฌ๋ผ์ง๋ค.
๋์ฉ๋ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ๋ ํจ์จ์ ๋์ด๊ธฐ ์ํด, ์คํ ๋ฐ์ฑ/์ธ๋ฐ์ฑ ๊ณผ์ ์ด ํ์ ์๋ Intstream
๊ณผ ๊ฐ์ ๊ธฐ๋ณธํ ์คํธ๋ฆผ๋ ์ ๊ณตํ๋ค.
์คํธ๋ฆผ์ ์์
๋ค์ ์ด๋๋ก๋ถํฐ๋ ์ฌ ์ ์ ๋ค. ๋ํ์ ์ผ๋ก๋ ์ปฌ๋ ์
, ๋ฐฐ์ด, ํ์ผ, ์ ๊ทํํ์ ํจํด ๋งค์ฒ(matcher), ๋์ ์์ฑ๊ธฐ, ํน์ ๋ค๋ฅธ ์คํธ๋ฆผ์ด ์๋ค.
{% hint style="info" %} ์คํธ๋ฆผ ์์ ๋ฐ์ดํฐ ์์๋ค์ ๊ฐ์ฒด ์ฐธ์กฐ๋ ๊ธฐ๋ณธ ํ์ ๊ฐ์ด๋ค. ๊ธฐ๋ณธ ํ์ ๊ฐ์ผ๋ก๋ int, long, double์ ์ง์ํ๋๋ฐ ๊ธฐ๋ณธ ํ์ ์ ๊ฒฝ์ฐ IntStream, LongStream, DoubleStream๊ณผ ๊ฐ์ Stream์ ์ฌ์ฉํ๋๊ฒ ์ฑ๋ฅ์ ์ข๋ค. {% endhint %}
- Stream - ๊ฐ์ฒด ์ฐธ์กฐ์ ๋ํ Stream
- IntStream - int ํ์ ์ ๋ํ Stream
- LongStream - long ํ์ ์ ๋ํ Stream
- DoubleStream - double ํ์ ์ ๋ํ Stream
๐ ์คํธ๋ฆผ์ ์ถ์ ๊ฐ๋
1. ์คํธ๋ฆผ(stream) : ๋ฐ์ดํฐ ์์์ ์ ํ ํน์ ๋ฌดํ ์ํ์ค
2. ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ(stream pipeline) : ์ด ์์๋ค๋ก ์ํํ๋ ์ฐ์ฐ ๋จ๊ณ๋ฅผ ํํ
์ด๋ฏธ์ง ๋ถ์
- Stream Source: ๋ฐฐ์ด, ์ปฌ๋ ์ , I/O ์ฑ๋ ๋ฑ ๋ค์ํ ์์ค์์ ์คํธ๋ฆผ์ ์์ฑํ ์ ์์์ ๋ํ๋ธ๋ค.
- Intermediate Operations: ํํฐ๋ง, ์ ๋ ฌ, ํ์ ๋ณํ, ๋งคํ ๋ฑ์ ์ค๊ฐ ์ฐ์ฐ์ด ํฌํจ๋๋ค. ์ด ์ฐ์ฐ๋ค์ ์คํธ๋ฆผ์ ๊ณ์ ๋ฐํํ๋ฉฐ, ๋ฉ์๋ ์ฒด์ด๋ ์คํ์ผ๋ก ์ฐ๋ฌ์ ์ ์ฉํ ์ ์๋ค.
- Terminal Operation: ์คํธ๋ฆผ์ ์๋นํ์ฌ ์ต์ข
๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ์ฐ์ฐ์ด๋ค. ์๋ฅผ ๋ค์ด
collect
,sum
,count
์ ๊ฐ์ ์ฐ์ฐ๋ค์ด ์๋ค. - Operation Result: ์ต์ข ์ฐ์ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ถ๋ถ
https://sas-study.tistory.com/239 ์ด๋ฏธ์ง ์ฐธ๊ณ
์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์์ค ์คํธ๋ฆผ์์ ์์ํด ์ข ๋จ ์ฐ์ฐ์ผ๋ก ๋๋๋ฉฐ, ๊ทธ ์ฌ์ด์ ํ๋ ์ด์์ ์ค๊ฐ ์ฐ์ฐ์ด ์์ ์ ์๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์์ฐจ์ ์ผ๋ก ์ํ๋๋๋ฐ, ํ์ดํ๋ผ์ธ์ ๋ณ๋ ฌ๋ก ์คํํ๋ ค๋ฉด ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ๋ ์คํธ๋ฆผ ์ค ํ๋์
parallel ๋ฉ์๋
๋ฅผ ํธ์ถํด ์ฌ์ฉํ๋ฉด ๋๊ธดํ๋, ํจ๊ณผ๋ฅผ ๋ณผ ์ ์๋ ์ํฉ์ ๋ง์ง ์๋ค.
๊ฐ ์ค๊ฐ ์ฐ์ฐ์ ์คํธ๋ฆผ์ ์ด๋ ํ ๋ฐฉ์์ผ๋ก ๋ณํํ๋ ์ญํ ์ ์ํํ๋ฉฐ, ๋ชจ๋ ํ ์คํธ๋ฆผ์ ๋ค๋ฅธ ์คํธ๋ฆผ์ผ๋ก ๋ณํํ๊ฒ ํ์ฌ ๋ฉ์๋ ์ฒด์ด๋์ ๊ฐ๋ฅํ๊ฒ ํ๋ค. ๋ณํ ๋ ์คํธ๋ฆผ์ ์์ ํ์ ์ ๋ณํ ์ ์คํธ๋ฆผ์ ์์ ํ์ ๊ณผ ๊ฐ์ ์๋ ์๊ณ ๋ค๋ฅผ ์๋ ์๋ค. ์๋ฅผ ๋ค์ด, ๊ฐ ์์์ ํจ์๋ฅผ ์ ์ฉํ๊ฑฐ๋ ํน์ ์กฐ๊ฑด์ ๋ง์กฑ ๋ชปํ๋ ์์๋ฅผ ๊ฑธ๋ฌ๋ผ ์ ์๋ค.
filter()
,map()
,sorted()
๋ฉ์๋ | ์ค๋ช |
---|---|
filter(Predicate<? super T> predicate) |
์ง์ ๋ predicate ํจ์์ ๋ง๋ ์์๋ง ์คํธ๋ฆผ์ ํฌํจํ๋๋ก ํํฐ๋ง |
map(Function<? super T, ? extends R> function) |
์คํธ๋ฆผ์ ๊ฐ ์์์ function ์ ์ ์ฉํ์ฌ ์๋ก์ด ์์๋ก ๋ณํ |
flatMap(Function<? super T, ? extends Stream<? extends R>> function) |
๊ฐ ์์์ function ์ ์ ์ฉํ์ฌ ์์ฑ๋ ์คํธ๋ฆผ์ ํ๋์ ์คํธ๋ฆผ์ผ๋ก ํํํ |
distinct() |
์คํธ๋ฆผ์ ์ค๋ณต ์์๋ฅผ ์ ๊ฑฐ |
sorted() |
์์๋ฅผ ๊ธฐ๋ณธ ์ ๋ ฌ(์ค๋ฆ์ฐจ์) |
sorted(Comparator<? super T> comparator) |
์ง์ ๋ comparator ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์์๋ฅผ ์ ๋ ฌ |
skip(long n) |
์คํธ๋ฆผ์ ์ฒซ n ๊ฐ์ ์์๋ฅผ ๊ฑด๋๋ |
limit(long maxSize) |
์คํธ๋ฆผ์ ์์ ์ค ์ต๋ maxSize ๊ฐ์๋งํผ๋ง ๋ฐํ๋ค. |
์ข ๋จ ์ฐ์ฐ์ ๋ง์ง๋ง ์ค๊ฐ ์ฐ์ฐ์ด ๋ด๋์ ์คํธ๋ฆผ์ ์ตํ์ ์ฐ์ฐ์ ๊ฐํ๋ ์ญํ ์ ํ๋ค.์๋ฅผ ๋ค์ด, ์์๋ฅผ ์ ๋ ฌํด ์ปฌ๋ ์ ์ ๋ด๊ฑฐ๋ ํน์ ์์๋ฅผ ํ๋ ์ ํํ๋ ์์ด๋ค.
forEach()
,collect()
,match()
,count()
,reduce()
Java Stream API์ ์ถ๊ฐ ๋ฉ์๋์ ์ค๋ช ์ ํ๋ก ์ ๋ฆฌํ์ต๋๋ค.
๋ฉ์๋ | ์ค๋ช |
---|---|
forEach(Consumer<? super T> consumer) |
์คํธ๋ฆผ์ ๊ฐ ์์๋ฅผ consumer ์ ์ ๋ฌํ์ฌ ์ํํ๋ฉฐ ์๋นํ๋ค. |
count() |
์คํธ๋ฆผ ๋ด์ ์์ ๊ฐ์๋ฅผ ๋ฐํํ๋ค. |
max(Comparator<? super T> comparator) |
comparator ๋ฅผ ์ฌ์ฉํ์ฌ ์คํธ๋ฆผ ๋ด์ ์ต๋ ๊ฐ์ ๋ฐํํ๋ค. |
min(Comparator<? super T> comparator) |
comparator ๋ฅผ ์ฌ์ฉํ์ฌ ์คํธ๋ฆผ ๋ด์ ์ต์ ๊ฐ์ ๋ฐํํ๋ค. |
allMatch(Predicate<? super T> predicate) |
์คํธ๋ฆผ์ ๋ชจ๋ ์์๊ฐ predicate ์ ๋ง์กฑํ๋ฉด true ๋ฅผ ๋ฐํํ๋ค. |
anyMatch(Predicate<? super T> predicate) |
์คํธ๋ฆผ์ ์์ ์ค ํ๋๋ผ๋ predicate ์ ๋ง์กฑํ๋ฉด true ๋ฅผ ๋ฐํํ๋ค. |
sum() |
์คํธ๋ฆผ์ ์์ ํฉ๊ณ๋ฅผ ๋ฐํํ๋ค. (IntStream , LongStream , DoubleStream ์ ์ฌ์ฉ) |
average() |
์คํธ๋ฆผ์ ์์ ํ๊ท ๊ฐ์ ๋ฐํํ๋ค. (IntStream , LongStream , DoubleStream ์ ์ฌ์ฉ) |
List<Integer> transactionsIds =
transactions.stream()
.filter(t -> t.getType() == Transaction.GROCERY)
.sorted(comparing(Transaction::getValue).reversed())
.map(Transaction::getId)
.collect(toList());
- Stream<Transaction> ์์ฑ: ๋ค์ํ
Transaction
๊ฐ์ฒด๋ค์ด ์คํธ๋ฆผ์ ํฌํจ๋์ด ์๋ค. filter
๋จ๊ณ:t -> t.getType() == Transaction.GROCERY
์กฐ๊ฑด์ ๋ง์กฑํ๋Transaction
๊ฐ์ฒด๋ค๋ง ํํฐ๋งํ์ฌStream<Transaction>
์ ์์ฑํ๋ค.sorted
๋จ๊ณ:Transaction
๊ฐ์ฒด๋ค์ ๊ฐ (getValue()
) ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌํ๋ค.map
๋จ๊ณ: ๊ฐTransaction
๊ฐ์ฒด์id
๋ง ์ถ์ถํ์ฌStream<Integer>
๋ก ๋ณํํ๋ค.collect
๋จ๊ณ: ์ต์ข ์ ์ผ๋กcollect(toList())
๋ฅผ ์ฌ์ฉํ์ฌList<Integer>
๋ก ๊ฒฐ๊ณผ๋ฅผ ์์งํ๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ์ด ์คํธ๋ฆผ ์์ ์ ํน์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ํธ๋์ญ์ ์ ํํฐ๋งํ๊ณ , ์ ๋ ฌํ ํ, ID๋ง ์์งํ์ฌ ๋ฆฌ์คํธ๋ก ๋ฐํํ๋ ๊ณผ์ ์ด๋ค.
์ง์ฐํ๊ฐ๋ ์ข ๋จ ์ฐ์ฐ์ด ํธ์ถ๋ ๋ ์ด๋ค์ง๋ฉฐ, ์ข ๋จ ์ฐ์ฐ์ ์ฐ์ด์ง ์๋ ๋ฐ์ดํฐ ์์๋ ๊ณ์ฐ์ ์ฐ์ด์ง ์๋๋ค. ์ด ํ ์ง์ฐ ํ๊ฐ๊ฐ ๋ฌดํ ์คํธ๋ฆผ์ ๋ค๋ฃฐ ์ ์๊ฒ ํด์ฃผ๋ ์ด์ ๋ค. ์ข ๋จ ์ฐ์ฐ์ด ์๋ ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์๋ฌด ์ผ๋ ํ์ง ์๋ ๋ช ๋ น์ด์ธ no-op๊ณผ ๊ฐ์ผ๋, ์ข ๋จ ์ฐ์ฐ์ ๋นผ๋จน๋ ์ผ์ด ์ ๋ ์๋๋ก ํ์.
๋จผ์ ์ง์ฐ์ด๋ ๊ฒฐ๊ณผ๊ฐ์ด ํ์ํ ๋๊น์ง ๊ณ์ฐ์ ๋ฆ์ถ๋ ๊ธฐ๋ฒ์ ์๋ฏธํ๋ค. ์ด๋ ๊ฒ ํจ์ผ๋ก์จ ์ด๋ ๋ถ๋ถ์์ ๊ฐ์ฅ ํฐ ์ด์ต์ ์ป์ ์ ์์๊น?
๋์ฉ๋์ ๋ฐ์ดํฐ์์, ์ค์ ๋ก ํ์ํ์ง ์์ ๋ฐ์ดํฐ๋ค์ ํ์ํ๋ ๊ฒ์ ๋ฐฉ์งํด ์๋๋ฅผ ๋์ผ ์ ์๋ค. ์ฆ, ์ข ๋จ ์ฐ์ฐ์ ์ฐ์ด์ง ์๋ ๋ฐ์ดํฐ ์์๋ ๊ณ์ฐ ์์ฒด์ ์ฐ์ด์ง ์๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์
Short-Circuit
๋ฐฉ์์ด๋ผ ๋ถ๋ฅธ๋ค.
https://www.logicbig.com/tutorials/core-java-tutorial/java-util-stream/short-circuiting.html
Java Stream API์์ "Short-circuiting Operations"(๋จ๋ฝ ์ฐ์ฐ)
{% hint style="info" %} ๋จ๋ฝ ์ฐ์ฐ์ ์ ์ฒด ์คํธ๋ฆผ์ ์ฒ๋ฆฌํ์ง ์๊ณ ๋ ์กฐ๊ฑด์ ๋ฐ๋ผ ์คํธ๋ฆผ ์ฒ๋ฆฌ๋ฅผ ์กฐ๊ธฐ์ ์ข ๋ฃํ ์ ์๋ ์ฐ์ฐ์ ์๋ฏธํ๋ค. {% endhint %}
- Intermediate Operation (์ค๊ฐ ์ฐ์ฐ):
limit()
: ์คํธ๋ฆผ์์ ์์์ ๊ฐ์๋ฅผ ์ ํํ๋ค. ์๋ฅผ ๋ค์ดlimit(5)
๋ ์คํธ๋ฆผ์ ์ฒ์ 5๊ฐ ์์๋ง์ ํฌํจํ๋ ์๋ก์ด ์คํธ๋ฆผ์ ์์ฑํ๋ค.limit()
๋ ์ค๊ฐ ์ฐ์ฐ์ผ๋ก ์คํธ๋ฆผ์ ๊ณ์ํด์ ๋ณํํ ์ ์๋ค.
- Terminal Operations (์ข
๊ฒฐ ์ฐ์ฐ):
findFirst()
: ์คํธ๋ฆผ์ ์ฒซ ๋ฒ์งธ ์์๋ฅผ ๋ฐํํ๋ค. ์กฐ๊ฑด์ ๋ง๋ ์ฒซ ๋ฒ์งธ ์์๊ฐ ๋ฐ๊ฒฌ๋๋ฉด ๋๋จธ์ง ์์๋ฅผ ํ์ํ์ง ์๋๋ค.findAny()
: ๋ณ๋ ฌ ์คํธ๋ฆผ์์๋ ์ฒซ ๋ฒ์งธ๊ฐ ์๋ ์์์ ์์๋ฅผ ๋ฐํํ ์ ์๋ค. ์กฐ๊ฑด์ ๋ง๋ ์์์ ์์๋ฅผ ์ฐพ์ผ๋ฉด ์คํธ๋ฆผ ์ฒ๋ฆฌ๋ฅผ ์ข ๋ฃํ๋ค.anyMatch()
: ์คํธ๋ฆผ์ ์์ ์ค ํ๋๋ผ๋ ์กฐ๊ฑด์ ๋ง์กฑํ๋์ง ๊ฒ์ฌํ๋ค. ์กฐ๊ฑด์ ๋ง๋ ์์๊ฐ ๋ฐ๊ฒฌ๋๋ฉด ๋๋จธ์ง๋ฅผ ํ์ธํ์ง ์๊ณ ์ข ๋ฃํ๋ค.allMatch()
: ์คํธ๋ฆผ์ ๋ชจ๋ ์์๊ฐ ์กฐ๊ฑด์ ๋ง์กฑํ๋์ง ๊ฒ์ฌํ๋ค. ํ๋๋ผ๋ ์กฐ๊ฑด์ ๋ง์ง ์๋ ์์๊ฐ ์์ผ๋ฉด ์คํธ๋ฆผ ์ฒ๋ฆฌ๋ฅผ ์ข ๋ฃํ๋ค.noneMatch()
: ์คํธ๋ฆผ์ ๋ชจ๋ ์์๊ฐ ์กฐ๊ฑด์ ๋ง์กฑํ์ง ์๋์ง ๊ฒ์ฌํ๋ค. ํ๋๋ผ๋ ์กฐ๊ฑด์ ๋ง๋ ์์๊ฐ ์์ผ๋ฉด ์คํธ๋ฆผ ์ฒ๋ฆฌ๋ฅผ ์ข ๋ฃํ๋ค.
- Limiting a size:
limit()
์ฐ์ฐ์ ํตํด ์คํธ๋ฆผ์ ํฌ๊ธฐ๋ฅผ ์ ํํ ์ ์๋ค. - Finding an element:
findFirst()
์findAny()
๋ฅผ ์ฌ์ฉํ์ฌ ํน์ ์์๋ฅผ ์ฐพ์ ์ ์์ผ๋ฉฐ, ์์๋ฅผ ์ฐพ์ผ๋ฉด ์ฐ์ฐ์ด ์ข ๋ฃ - Testing a match:
anyMatch()
,allMatch()
,noneMatch()
์ฐ์ฐ์ ์ฌ์ฉํ์ฌ ์กฐ๊ฑด์ ๋ง๋ ์์๊ฐ ์๋์ง ํ์ธํ ์ ์๋ค.
์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์คํํ๊ฒ ๋๋ฉด, JVM
์ ๊ณง๋ฐ๋ก ์คํธ๋ฆผ ์ฐ์ฐ์ ์คํ์ํค์ง ์๋๋ค. ์ต์ํ์ผ๋ก ํ์์ ์ธ ์์
๋ง ์ํํ๊ณ ์ ๊ฒ์ฌ๋ฅผ ๋จผ์ ํ๊ณ , ์ด๋ฅผ ๋ฐํ์ผ๋ก ์ต์ ํ ๋ฐฉ๋ฒ์ ์ฐพ์๋ด ๊ณํํ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ๊ณํ์ ๋ฐ๋ผ ๊ฐ๋ณ ์์์ ๋ํ ์คํธ๋ฆผ ์ฐ์ฐ์ ์ํํ๋ค.
์๋ฅผ ๋ค์ด, 10000
๊ฐ์ ๋ฐ์ดํฐ์ค์ ๊ธธ์ด๊ฐ 5๊ฐ ๋๋ ๋ฌธ์์ด์์ ๊ฐ์ฅ ์ํ๋ฒณ์์ผ๋ก ์์ ์๋ 2๊ฐ์ ๋ฌธ์์ด๋ง ๊ฐ์ง๊ณ ์ค๊ณ ์ถ๋ค๊ณ ํ์. ์ง์ฐ ํ๊ฐ๊ฐ ์์ด ์์๋๋ก ๋ฐ๋ก ๋์ํ๋ค๋ฉด, 10000
๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ์ํํด์ผ ํ์ ๊ฒ์ด๋ค.
ํ์ง๋ง ์ด์งํผ ์ต์ข ์ ์ผ๋ก 2๊ฐ๋ง ํ์ํ๋ฉด ๋๋๋ฐ ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ๋ค ๋ณผ ํ์๊ฐ ์์๊น?
๊ฒฐ๊ณผ๋ฅผ ๋ด๋ณด์. limit(n)
์ฐ์ฐ์ด ๋ด๋ถ์ ์ผ๋ก ์์ ์๊ฒ ๋๋ฌํ ์์๊ฐ n
๊ฐ๊ฐ ๋์์ ๋ ์คํธ๋ฆผ ๋ด ๋ค๋ฅธ ์์๋ค์ ๋ํด ๋ ์ด์ ์ํํ์ง ์๊ณ ํ์ถํ๋๋ก ๋ง๋ค์๊ธฐ ๋๋ฌธ์, ๊ธธ์ด๊ฐ 5
๊ฐ ๋๋ ๋ฐ์ดํฐ 4
๊ฐ๊ฐ ์๋, ๋งจ ์์ 2
๊ฐ ๋ฐ์ดํฐ๊ฐ ์ถ๋ ฅ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.\
์ด๋ฌํ ์ง์ฐ ํ๊ฐ ํน์ฑ์ผ๋ก ์ธํด, ์ฐ๋ฆฌ๋ ๋ฌดํ ์คํธ๋ฆผ์ ๋ค๋ฃฐ ์ ์๊ฒ ๋๋ค.
๋ฌดํ ์คํธ๋ฆผ์ ์ ์ด์ ํฌ๊ธฐ๊ฐ ์ ํด์ ธ ์์ง ์์ ๋งํผ, ์ค๋ณต ์ ๊ฑฐ๋ฅผ ํ์ง ๋ชปํ๋ค . ํ์ง๋ง limit()
๊ณผ ๊ฐ์ short-circuit
์ฐ์ฐ์ ํตํด ์ ํ ์คํธ๋ฆผ์ผ๋ก ๋ณํคํจ์ผ๋ก์จ ๊ฐ๋ฅํด์ง๋ค.
๐ ์ ํ ์คํธ๋ฆผ vs ๋ฌดํ ์คํธ๋ฆผ
1. ์ ํ ์คํธ๋ฆผ : ์์ฑํ ๋ ํฌ๊ธฐ๊ฐ ์ ํด์ ธ ์๋ ์คํธ๋ฆผIntStream ints(long streamsize, int begin, int end)2.๋ฌดํ ์คํธ๋ฆผ : ๋ฌดํํ ํฌ๊ธฐ๋ก ๊ฐ์ ๊ฐ์ง๋ ์คํธ๋ฆผ
IntStream ints(int begin, int end)
์ด์ฒ๋ผ ์ค๋ณต์ ์ ๊ฑฐํ๋ distinct()
๋, ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฌํ๋ sort()
์ฐ์ฐ๋ค์ Stateful
์ฐ์ฐ์ด๋ผ ํ๋ค. ํ์ง๋ง ์ด๋ ์ง์ฐ ํ๊ฐ๋ฅผ ๋ฌดํจํ์ํค๊ณ , ๊ฒฐ๊ณผ๋ฅผ ์์ฑํ๊ธฐ ์ ์ ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ํ์ํ๋ ๊ฒฐ๊ณผ๋ฅผ ์ด๋ํ๋ค. ์์๋ฅผ ๋ด๋ณด์.
limit()
์ ๊ฑธ์ด์ฃผ์์์๋, sorted()
์ผ๋ก ์ธํด ๊ธธ์ด๊ฐ 5
๊ฐ ๋๋ ๋ชจ๋ ๋ค๊ฐ์ ๋ฐ์ดํฐ๋ค์ ํ์ํ ํ์๊ฐ ์๊ฒจ ์ง์ฐ ํ๊ฐ๊ฐ ์ด๋ฃจ์ด์ง์ง ์์ ๊ฒ์ ๋ณผ ์ ์๋ค.
2. ์์ฐจ์ฑ
๊ธฐ๋ณธ์ ์ผ๋ก ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์์ฐจ์ ์ผ๋ก ์ํ๋๋ค. ํ์ดํ๋ผ์ธ์ ๋ณ๋ ฌ๋ก ์คํํ๋ ค๋ฉด, ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ๋ ์คํธ๋ฆผ ์ค ํ๋์์ parallel
๋ฉ์๋๋ฅผ ํธ์ถํด์ฃผ๊ธฐ๋ง ํ๋ฉด ๋๋, ํจ๊ณผ๋ฅผ ๋ณผ ์ ์๋ ์ํฉ์ ๋ง์ง ์๋ค.
์คํธ๋ฆผ์ ์ ๋๋ก ์ฌ์ฉํ๋ฉด ํ๋ก๊ทธ๋จ์ด ์งง๊ณ ๊น๋ํด์ง์ง๋ง, ์๋ชป ์ฌ์ฉํ๋ฉด ์ฝ๊ธฐ ์ด๋ ต๊ณ ์ ์ง๋ณด์๊ฐ ํ๋ค๋ค. ๊ทธ๋ ๋ค๋ฉด ๋ฐฉ๋ฒ์?
1. ๋ชจ๋ ๋ฐ๋ณต๋ฌธ์ ์คํธ๋ฆผ์ผ๋ก ๋ฐ๊พธ๊ธฐ ๋ณด๋ค, ๋ฐ๋ณต๋ฌธ๊ณผ ์คํธ๋ฆผ์ ์ ์ ํ ์กฐํฉํ์.
๋ค์ ์ฝ๋์ ์์๋ฅผ ๋ค์ด ์ค๋ช ํด๋ณด๊ฒ ๋ค. ์ด ํ๋ก๊ทธ๋จ์, ์ฌ์ ํ์ผ์์ ๋จ์ด๋ฅผ ์ฝ์ด ์ฌ์ฉ์๊ฐ ์ง์ ํ ๋ฌธํฑ๊ฐ๋ณด๋ค ์์ ์๊ฐ ๋ง์ ์๋๊ทธ๋จ ๊ทธ๋ฃน์ ์ถ๋ ฅํ๋ค. (์ฒ ์๋ฅผ ๊ตฌ์ฑํ๋ ์ํ๋ฒณ์ด ๊ฐ๊ณ ์์๋ง ๋ค๋ฅธ ๋จ์ด)
public class Anagrams {
public static void main(String[] args) throws IOException {
File dictionary = new File(args[0]);
int minGroupSize = Interger.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);
}
public static String alphabetie(String s){
char[] a = s.toCharArray();
Arrays.sort(a);
return new String(a);
}
}
computeIfAbsent()
: ๋งต ์์ ํค๊ฐ ์๋ค๋ฉด ๋งคํ๋ ๊ฐ์ ๋ฐํํ๊ณ ์๋ค๋ฉด ๊ฑด๋ค์ง ํจ์ ๊ฐ์ฒด๋ฅผ ํค์ ์ ์ฉํ์ฌ ๊ฐ์ ๊ณ์ฐํ ๋ค์ ํค์ ๊ฐ์ ๋งคํํด๋๊ณ , ๊ณ์ฐ๋ ๊ฐ์ ๋ฐํ
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);
}
}
}
์คํธ๋ฆผ์ ๊ณผํ๊ฒ ํ์ฉํ์ฌ, ์ฌ์ ํ์ผ ์ฌ๋ ๋ถ๋ถ์ ์ ์ธํ๊ณ ํ๋ก๊ทธ๋จ ์ ์ฒด๊ฐ ๋จ ํ๋์ ํํ์์ผ๋ก ์ฒ๋ฆฌ๋๊ณ ์๋ค. ์ด์ฒ๋ผ ์คํธ๋ฆผ์ ๊ณผ์ฉํ๋ฉด ํ๋ก๊ทธ๋จ์ด ์ฝ๊ฑฐ๋ ์ ์ง๋ณด์ํ๊ธฐ ์ด๋ ค์์ง๋ค.
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));
}
alphabetize()
๊ณผ ๊ฐ์ ์ธ๋ถ ๊ตฌํ์ ์ฃผ ํ๋ก๊ทธ๋จ ๋ก์ง ๋ฐ์ผ๋ก ๋นผ๋ด ์ ์ฒด์ ์ธ ๊ฐ๋
์ฑ์ ๋์๋ค. ์ด์ฒ๋ผ ๋์ฐ๋ฏธ ๋ฉ์๋๋ฅผ ์ ์ ํ ํ์ฉํ๋ ์ผ์ ์ค์์ฑ์ ์ผ๋ฐ ๋ฐ๋ณต ์ฝ๋์์๋ณด๋ค๋ ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์์ ํจ์ฌ ์ปค์ง๋ค.
๐ ๋๋ค์์๋ ํ์ ์ด๋ฆ์ ์์ฃผ ์๋ตํ๋ฏ๋ก, ๋งค๊ฐ๋ณ์์ ์ด๋ฆ์ ์ ์ง์ด์ผ ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ๊ฐ๋ ์ฑ์ด ์ ์งํ ์ ์๋ค.
์๋ฐ๋ ๊ธฐ๋ณธ ํ์
์ธ char
์ฉ ์คํธ๋ฆผ์ ์ง์ํ์ง ์๋๋ค. ๋ฐ๋ผ์ ์๋ ์ฝ๋๋ฅผ ์คํ์์ผ๋ณด๋ฉด ์ ์๊ฐ์ด ์ถ๋ ฅ๋๋ค. ์ฐธ๊ณ ๋ก boolean[]
, byte[]
, short[]
, char[]
, float[]
๋ ํด๋น ํ์
์ ๊ธฐ๋ณธํ ์คํธ๋ฆผ์ด ์กด์ฌํ์ง ์๋๋ค.
"Hello World!".chars().forEach(System.out::print); // ์ ์๊ฐ์ด ์ถ๋ ฅ๋จ : 739488237102..
์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ๋ํ์ด ๋๋ ๊ณ์ฐ์ ์ฃผ๋ก ํจ์ ๊ฐ์ฒด(๋๋ค/๋ฉ์๋ ์ฐธ์กฐ)๋ก ํํํ๊ณ ๋ฐ๋ณต ์ฝ๋์๋ ์ฝ๋ ๋ธ๋ก์ ์ฌ์ฉํด ํํํ๋ค.
์คํธ๋ฆผ๊ณผ ํจ์ ๊ฐ์ฒด๋ก๋ ํ ์ ์์ง๋ง, ์ฝ๋ ๋ธ๋ก์ผ๋ก๋ ํ ์ ์๋ ๊ฒฝ์ฐ๋ฅผ ๊ตฌ๋ถํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
- ์ฝ๋ ๋ธ๋ก์์๋ ๋ฒ์ ์์ ์ง์ญ๋ณ์๋ฅผ ์ฝ๊ณ ์์ ํ ์ ์๋ค. ํ์ง๋ง ๋๋ค์์๋ ์ฌ์ค์
final
์ธ ๋ณ์๋ง ์ฝ์ ์ ์๊ณ , ์ง์ญ๋ณ์ ์์ ์ ๋ถ๊ฐ๋ฅํ๋ค. - ์ฝ๋ ๋ธ๋ก์์๋
return
/break
/continue
๋ฌธ์ผ๋ก ๋ธ๋ก์ ํ๋ฆ์ ์ ์ดํ๊ฑฐ๋, ๋ฉ์๋ ์ ์ธ์ ๋ช ์๋ ๊ฒ์ฌ ์์ธ๋ฅผ ๋์ง ์ ์๋ค. ํ์ง๋ง ๋๋ค๋ ๋ถ๊ฐ๋ฅํ๋ค.
- ์์๋ค์ ์ํ์ค๋ฅผ ์ผ๊ด๋๊ฒ ๋ณํํด์ผ ํ๋ ๊ฒฝ์ฐ :
map()
- ์์๋ค์ ์ํ์ค๋ฅผ ํํฐ๋ง ํด์ผ ํ๋ ๊ฒฝ์ฐ :
filter()
- ์์๋ค์ ์ํ์ค๋ฅผ ํ๋์ ์ฐ์ฐ์ ์ฌ์ฉํด ๊ฒฐํฉํด์ผ ํ๋ ๊ฒฝ์ฐ(๋ํ๊ธฐ, ์ฐ๊ฒฐํ๊ธฐ, ์ต์๊ฐ ๊ตฌํ๊ธฐ ๋ฑ) :
- ์์๋ค์ ์ํ์ค๋ฅผ ์ปฌ๋ ์
์ ๋ชจ์ผ๋ ๊ฒฝ์ฐ(๊ณตํต๋ ์์ฑ์ ๊ธฐ์ค์ผ๋ก) :
collect()
- ์์๋ค์ ์ํ์ค์์ ํน์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์์๋ฅผ ์ฐพ์ ๊ฒฝ์ฐ :
filter()
ํ ๋ฐ์ดํฐ๊ฐ ํ์ดํ๋ผ์ธ์ ์ฌ๋ฌ ๋จ๊ณ๋ฅผ ํต๊ณผํด์ผํ ๋, ์ด ๋ฐ์ดํฐ์ ๊ฐ ๋จ๊ณ์์์ ๊ฐ๋ค์ ๋์์ ์ ๊ทผํ๋ ๊ฒฝ์ฐ์๋ ์คํธ๋ฆผ์ ์ฌ์ฉํ๊ธฐ ํ๋ค๋ค. ํ์ดํ๋ผ์ธ์ ์ผ๋จ ํ ๊ฐ์ ๋ค๋ฅธ ๊ฐ์ ๋งคํํ๊ณ ๋๋ฉด ์๋์ ๊ฐ์ ์๋ ๊ตฌ์กฐ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
๐ ํต์ฌ ์ ๋ฆฌ
์คํธ๋ฆผ๊ณผ ๋ฐ๋ณต ์ค ์ด๋์ชฝ์ด ๋์์ง ํ์ ํ๊ธฐ ์ด๋ ต๋ค๋ฉด, ๋ ๋ค ํ ์คํธํด๋ณด๊ณ ๋ ๋์ ์ชฝ์ ํํ๋ ๊ฒ์ด ์ข๋ค.
์ถ์ฒ ๋ฐ ์ฐธ๊ณ https://www.logicbig.com/tutorials/core-java-tutorial/java-util-stream/short-circuiting.html
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#Statelessness
https://bugoverdose.github.io/development/stream-lazy-evaluation/