λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

Java/Java의 정석

Chapter 14 - λžŒλ‹€μ™€ 슀트림

Chapter 14 - λžŒλ‹€μ™€ 슀트림

1. λžŒλ‹€μ‹

  • JDK 1.8λΆ€ν„° μΆ”κ°€
  • ν•¨μˆ˜ν˜• μ–Έμ–΄μ˜ κΈ°λŠ₯κΉŒμ§€ κ°–μΆ”κ²Œ 함
    • ν•¨μˆ˜ν˜• μ–Έμ–΄μ˜ μž₯점듀을 μžλ°”μ—μ„œλ„ μ‚¬μš©

1.1 λžŒλ‹€μ‹μ΄λž€?

  • λ©”μ„œλ“œλ₯Ό ν•˜λ‚˜μ˜ 식(expression)으둜 ν‘œν˜„ν•œ 것
    • κ°„λž΅ & λͺ…ν™•ν•œ μ‹μœΌλ‘œ ν•¨μˆ˜λ₯Ό ν‘œν˜„
    • λ©”μ„œλ“œμ˜ 이름과 λ°˜ν™˜κ°’μ΄ μ—†μ–΄μ§€λ―€λ‘œ 읡λͺ…ν•¨μˆ˜λΌκ³ λ„ 뢀름
    • λ©”μ„œλ“œλŠ” 객체지ν–₯μ—μ„œμ˜ ν•¨μˆ˜ (객체의 ν–‰μœ„λ‚˜ λ™μž‘μ„ 의미)

1.2 λžŒλ‹€μ‹ μž‘μ„±ν•˜κΈ°

  • 이름과 λ°˜ν™˜ νƒ€μž…μ„ μ œκ±°ν•˜κ³  λ§€κ°œλ³€μˆ˜ 선언뢀와 λͺΈν†΅ 사이에 -> μΆ”κ°€
    • λ°˜ν™˜κ°’μ΄ μžˆλ‹€λ©΄ return문을 μ‹μœΌλ‘œ λŒ€μ‹ ν•  수 있음(끝에 μ„Έλ―Έμ½œλ‘ μ„ 뢙이지 μ•ŠμŒ)
    • λ§€κ°œλ³€μˆ˜ νƒ€μž…μ€ 좔둠이 κ°€λŠ₯ν•œ 경우 μƒλž΅ (λ§€κ°œλ³€μˆ˜ 쀑 μ–΄λŠ ν•˜λ‚˜μ˜ λ§€κ°œλ³€μˆ˜λ§Œ μƒλž΅μ€ λΆˆκ°€λŠ₯)
    • λ§€κ°œλ³€μˆ˜κ°€ ν•˜λ‚˜λΏμ΄κ³  맀개 λ³€μˆ˜μ˜ νƒ€μž…μ΄ 없을 μ‹œ κ²½μš°μ—” κ΄„ν˜Έ μƒλž΅ κ°€λŠ₯
    • κ΄„ν˜Έ {}μ•ˆμ˜ λ¬Έμž₯이 ν•˜λ‚˜μΌ λ•ŒλŠ” κ΄„ν˜Έ μƒλž΅ κ°€λŠ₯, μ΄λ•Œλ„ 끝에 μ„Έλ―Έμ½œλ‘ μ„ 뢙이지 μ•Šμ•„μ•Ό ν•œλ‹€.

1.3 ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€(Functional Interface)

  • λžŒλ‹€μ‹μ€ 읡λͺ… 클래슀의 객체와 동등 (new Object() {~})
  • λžŒλ‹€λ‘œ μ •μ˜λœ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  λ•Œ ν•„μš”ν•œ 것듀
    • μ°Έμ‘° λ³€μˆ˜κ°€ ν•„μš”
    • μ°Έμ‘° λ³€μˆ˜λ₯Ό λ§Œλ“€κΈ° μœ„ν•΄μ„œλŠ” μ°Έμ‘° λ³€μˆ˜μ˜ νƒ€μž…μ΄ ν•„μš”
    • λžŒλ‹€μ‹κ³Ό λ™λ“±ν•œ λ©”μ„œλ“œλ₯Ό μ •μ˜ν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ§Œλ“  λ’€ μ°Έμ‘° λ³€μˆ˜μ˜ νƒ€μž…μœΌλ‘œ 지정
    • μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 클래슀λ₯Ό 'new νƒ€μž…'κ³Ό 같은 λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ν•  수 μžˆμ§€λ§Œ λžŒλ‹€μ‹μœΌλ‘œλ„ κ΅¬ν˜„ κ°€λŠ₯
    • (μ°Έμ‘° λ³€μˆ˜).(μΈν„°νŽ˜μ΄μŠ€μ— μ •μ˜λœ λ©”μ„œλ“œλͺ…)으둜 읡λͺ… 객체의 λ©”μ„œλ“œ 호좜
  • μœ„μ™€ 같은 κ³Όμ •μœΌλ‘œ 인해 μΈν„°νŽ˜μ΄μŠ€λ‘œ λžŒλ‹€μ‹μ„ λ‹€λ£¨κΈ°λ‘œ κ²°μ •
  • λžŒλ‹€μ‹μ„ 닀루기 μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λΌκ³  μ •μ˜
  • ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λŠ” ν•˜λ‚˜μ˜ 좔상 λ©”μ„œλ“œλ§Œ μ •μ˜ν•΄μ•Ό 됨
    • λžŒλ‹€μ‹κ³Ό μΈν„°νŽ˜μ΄μŠ€μ˜ λ©”μ„œλ“œλ₯Ό 1:1둜 μ—°κ²°ν•΄μ•Ό ν•˜κΈ° λ•Œλ¬Έ
    • static λ©”μ„œλ“œμ™€ default λ©”μ„œλ“œλŠ” μ œμ•½ X
  • @FunctionalInteface μ• λ„ˆν…Œμ΄μ…˜μ„ 뢙이면 μ»΄νŒŒμΌλŸ¬κ°€ μ •ν™•ν•œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μΈμ§€ 확인해 쀌

ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…μ˜ λ§€κ°œλ³€μˆ˜μ™€ λ°˜ν™˜ νƒ€μž…

  • λ©”μ„œλ“œμ˜ λ§€κ°œλ³€μˆ˜κ°€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…μΌ μ‹œ ν•΄λ‹Ή 인자둜 λžŒλ‹€μ‹μ„ μ°Έμ‘°ν•˜λŠ” μ°Έμ‘° λ³€μˆ˜λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ 지정해야 함
  • μ°Έμ‘° λ³€μˆ˜ 없이 직접 λžŒλ‹€μ‹μ„ λ§€κ°œλ³€μˆ˜λ‘œ μ§€μ •ν•˜λŠ” 것도 κ°€λŠ₯
  • λ³€μˆ˜μ²˜λŸΌ λ©”μ„œλ“œλ₯Ό μ£Όκ³ λ°›λŠ” 것이 κ°€λŠ₯해짐
    • 사싀상 λ©”μ„œλ“œκ°€ μ•„λ‹ˆλΌ 객체λ₯Ό μ£Όκ³ λ°›λŠ” κ²ƒμ΄μ§€λ§Œ μ½”λ“œκ°€ 더 간결해짐

λžŒλ‹€μ‹μ˜ νƒ€μž…κ³Ό ν˜•λ³€ν™˜

  • λžŒλ‹€μ‹μ˜ νƒ€μž…μ΄ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ˜ νƒ€μž…κ³Ό μ •ν™•νžˆ μΌμΉ˜ν•˜λŠ” 것은 μ•„λ‹˜
    • λžŒλ‹€μ‹μ˜ νƒ€μž… 좜λ ₯ μ‹œ μ™ΈλΆ€ν΄λž˜μŠ€μ΄λ¦„&&Lambda&&번호
    • ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ™€ μΌμΉ˜ν•˜κΈ° μœ„ν•œ ν˜• λ³€ν™˜μ΄ ν•„μš”ν•˜μ§€λ§Œ ν˜•λ³€ν™˜μ€ μƒλž΅ κ°€λŠ₯
  • Object둜의 ν˜•λ³€ν™˜μ€ λΆˆκ°€λŠ₯
    • λžŒλ‹€μ‹μ€ 였직 ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ‘œλ§Œ ν˜•λ³€ν™˜ κ°€λŠ₯

μ™ΈλΆ€ λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•˜λŠ” λžŒλ‹€μ‹

  • 읡λͺ… ν΄λž˜μŠ€μ™€ λ™μΌν•œ λ°©μ‹μœΌλ‘œ λžŒλ‹€μ‹λ„ 외뢀에 μ„ μ–Έλœ λ³€μˆ˜μ— μ ‘κ·Ό κ°€λŠ₯
  • λžŒλ‹€μ‹ λ‚΄μ—μ„œ μ°Έμ‘°ν•˜λŠ” μ§€μ—­λ³€μˆ˜λŠ” final이 뢙지 μ•Šμ•˜μ–΄λ„ μƒμˆ˜λ‘œ κ°„μ£Ό
  • μ™ΈλΆ€ μ§€μ—­λ³€μˆ˜μ™€ 같은 μ΄λ¦„μ˜ λžŒλ‹€μ‹ λ§€κ°œλ³€μˆ˜λŠ” ν—ˆμš© X

1.4 java.util.function νŒ¨ν‚€μ§€

  • λŒ€λΆ€λΆ„μ˜ λ©”μ„œλ“œλŠ” νƒ€μž…μ΄ λΉ„μŠ·ν•˜κ³  지넀릭 λ©”μ„œλ“œλ‘œ μ •μ˜ν•  수 있음
    • κ°€λŠ₯ν•˜λ©΄ 미리 μ •μ˜ν•΄ λ‘” μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν™œμš©
    • λ©”μ„œλ“œ 이름 톡일, μž¬μ‚¬μš©μ„±, μœ μ§€ 보수 μΈ‘λ©΄μ—μ„œ μ’‹μŒ
  • κ°€μž₯ 기본적인 ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€
    • run() : λ§€κ°œλ³€μˆ˜ X, λ°˜ν™˜κ°’ X
    • Supplier<T> : λ§€κ°œλ³€μˆ˜ X, λ°˜ν™˜κ°’ O
    • Consumer<T> : λ§€κ°œλ³€μˆ˜ O, λ°˜ν™˜κ°’ X
    • Function<T,R> : ν•˜λ‚˜μ˜ λ§€κ°œλ³€μˆ˜λ₯Ό λ°›μ•„μ„œ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λŠ” 일반적인 ν•¨μˆ˜
    • Predicate<T> : λ§€κ°œλ³€μˆ˜ ν•˜λ‚˜, boolean νƒ€μž… λ°˜ν™˜, 쑰건식을 ν‘œν˜„ν•˜λŠ” 데 μ‚¬μš©

μ‘°κ±΄μ‹μ˜ ν‘œν˜„μ— μ‚¬μš©λ˜λŠ” Predicate

  • PredicateλŠ” Functionμ—μ„œ λ°˜ν™˜ νƒ€μž…μ΄ booleanμ΄λΌλŠ” 차이
  • 쑰건식을 λžŒλ‹€μ‹μœΌλ‘œ ν‘œν˜„ν•˜λŠ” 데 μ‚¬μš©

λ§€κ°œλ³€μˆ˜κ°€ 두 개인 ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€

  • 이름 μ•žμ— 접두사 'Bi'κ°€ λΆ™μŒ
  • μ’…λ₯˜
    • BiConsumer<T,U> : 두 개의 λ§€κ°œλ³€μˆ˜, λ°˜ν™˜κ°’ X
    • BiPredicate<T,U> : 쑰건식을 ν‘œν˜„ν•˜λŠ” 데 μ‚¬μš©, λ§€κ°œλ³€μˆ˜λŠ” λ‘˜, λ°˜ν™˜κ°’μ€ boolean
    • BiFunction<T,U,R> : 두 개의 λ§€κ°œλ³€μˆ˜λ₯Ό λ°›μ•„μ„œ ν•˜λ‚˜μ˜ κ²°κ³Ό λ°˜ν™˜
  • 3개 μ΄μƒμ˜ λ§€κ°œλ³€μˆ˜λ₯Ό κ°–λŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λŠ” 직접 κ΅¬ν˜„ν•΄μ„œ μ‚¬μš© κ°€λŠ₯

UnaryOperator와 BinaryOperator

  • λ§€κ°œλ³€μˆ˜μ˜ νƒ€μž…κ³Ό λ°˜ν™˜ νƒ€μž…μ˜ νƒ€μž…μ΄ λͺ¨λ‘ μΌμΉ˜ν•˜λŠ” 점만 μ œμ™Έν•˜κ³ λŠ” Functionκ³Ό κ°™μŒ
  • μ’…λ₯˜
    • UnaryOperator<T> : Function의 μžμ†, λ§€κ°œλ³€μˆ˜μ™€ κ²°κ΄κ°’μ˜ νƒ€μž…μ΄ 동일
    • BinaryOperator<T> : Function의 μžμ†, 두 λ§€κ°œλ³€μˆ˜μ™€ κ²°κ΄κ°’μ˜ νƒ€μž…μ΄ 동일

μ»¬λ ‰μ…˜ ν”„λ ˆμž„μ›κ³Ό ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€

  • μ»¬λ ‰μ…˜ ν”„λ ˆμž„μ›μ˜ μΈν„°νŽ˜μ΄μŠ€μ˜ λ‹€μˆ˜μ˜ λ””ν΄νŠΈ λ©”μ„œλ“œ μΆ”κ°€
  • 그쀑 μΌλΆ€λŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©
  • Collection μΈν„°νŽ˜μ΄μŠ€
    • boolean removeif(Predicate<E> filter) : 쑰건에 λ§žλŠ” μš”μ†Œλ₯Ό μ‚­μ œ
  • List μΈν„°νŽ˜μ΄μŠ€
    • void replaceAll(UnaryOperator<E> operator) : λͺ¨λ“  μš”μ†Œλ₯Ό λ³€ν™˜ν•˜μ—¬ λŒ€μ²΄
  • Iterable μΈν„°νŽ˜μ΄μŠ€
    • void forEach(Consumer<T> action) : λͺ¨λ“  μš”μ†Œμ— μž‘μ—… action을 μˆ˜ν–‰
  • Map μΈν„°νŽ˜μ΄μŠ€
    • V compute(K key, BiFunction<K,V,V> f) : μ§€μ •λœ ν‚€μ˜ 값에 μž‘μ—… fλ₯Ό μˆ˜ν–‰
    • V computeIfAbsent(K key, Function<K,V> f) : ν‚€κ°€ μ—†μœΌλ©΄ μž‘μ—… f μˆ˜ν–‰ ν›„ μΆ”κ°€
    • V conputeIfPresent(K key, BiFunction<K,V,V> f) : μ§€μ •λœ ν‚€κ°€ μžˆμ„ λ•Œ μž‘μ—… f μˆ˜ν–‰
    • V merge(K key, V value, BiFunction<K,V,V> f) : λͺ¨λ“  μš”μ†Œμ— λ³‘ν•©μž‘μ—… fλ₯Ό μˆ˜ν–‰
    • void forEach(BiConsumer<K,V> action) : λͺ¨λ“  μš”μ†Œμ— μž‘μ—… action을 μˆ˜ν–‰
    • void replaceAll(BiFunction<K,V,V> f) : λͺ¨λ“  μš”μ†Œμ— μΉ˜ν™˜μž‘μ—… fλ₯Ό μˆ˜ν–‰

κΈ°λ³Έν˜•μ„ μ‚¬μš©ν•˜λŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€

  • κΈ°λ³Έν˜• λŒ€μ‹  래퍼 클래슀둜 μ‚¬μš©ν•˜λŠ” 것은 λΉ„νš¨μœ¨μ 
  • 보닀 효율적인 처리λ₯Ό μœ„ν•΄ κΈ°λ³Έν˜•μ„ μ‚¬μš©ν•˜λŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ“€ 제곡
  • μ’…λ₯˜
    • DoubleToIntFunction : μž…λ ₯이 double νƒ€μž…, 좜λ ₯이 int νƒ€μž…
    • ToIntFunction<T> : μž…λ ₯은 지넀릭, 좜λ ₯은 int νƒ€μž…
    • IntFunction<R> : μž…λ ₯이 int νƒ€μž…, 좜λ ₯은 지넀릭 νƒ€μž…
    • ObjIntConsumer<T> : μž…λ ₯이 지넀릭과 int, 좜λ ₯은 μ—†μŒ

1.5 Function의 ν•©μ„±κ³Ό Predicate κ²°ν•©

  • static λ©”μ„œλ“œλ‘œ μ •μ˜λ˜μ–΄ 있음

Function의 ν•©μ„±

  • 두 λžŒλ‹€μ‹μ„ ν•©μ„±ν•΄μ„œ μƒˆλ‘œμš΄ λžŒλ‹€μ‹μ„ λ§Œλ“€ 수 있음
  • f.andThen(g)
    • f의 결과값을 g둜 λ°›μ•„μ„œ 값을 λ°˜ν™˜
  • f.compose(g)
    • andThenκ³Ό λ°˜λŒ€
    • g의 결과값을 f둜 λ°›μ•„μ„œ 값을 λ°˜ν™˜
  • identity()
    • ν•­λ“± ν•¨μˆ˜κ°€ ν•„μš”ν•  λ•Œ μ‚¬μš©
    • λžŒλ‹€μ‹μœΌλ‘œ ν‘œν˜„ μ‹œ x->x
    • map()으둜 λ³€ν™˜μž‘μ—…ν•  λ•Œ λ³€ν™˜ 없이 κ·ΈλŒ€λ‘œ μ²˜λ¦¬ν•˜κ³ μž ν•  λ•Œ μ‚¬μš©

Predicate의 κ²°ν•©

  • 쑰건식듀을 논리 μ—°μ‚°μžλ‘œ ν•˜λ‚˜μ˜ μ‹μœΌλ‘œ ꡬ성할 수 μžˆλ“―μ΄ μ—¬λŸ¬ Predicate도 κ²°ν•© κ°€λŠ₯
  • and(), or(), negeate()둜 μ—°κ²°
  • negateλŠ” !의 의미

1.6 λ©”μ„œλ“œ μ°Έμ‘°

  • λžŒλ‹€μ‹μ„ λ”μš± κ°„κ²°ν•˜κ²Œ ν•  수 μžˆλŠ” 방법
  • λžŒλ‹€μ‹μ΄ ν•˜λ‚˜μ˜ λ©”μ„œλ“œλ§Œ ν˜ΈμΆœν•˜λŠ” κ²½μš°μ—λ§Œ μ‚¬μš©
  • μš°λ³€ λ©”μ„œλ“œμ˜ μ„ μ–Έ λΆ€λΆ„μ΄λ‚˜ μ’Œλ³€ μΈν„°νŽ˜μ΄μŠ€μ— μ§€μ •λœ 지넀릭 νƒ€μž…μœΌλ‘œλΆ€ν„° μ•Œμ•„λ‚Ό 수 μžˆλŠ” λ‚΄μš©μ„ μƒλž΅
  • ν‘œν˜„
    • static λ©”μ„œλ“œ, μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œ μ°Έμ‘°λŠ” ν΄λž˜μŠ€μ΄λ¦„::λ©”μ„œλ“œμ΄λ¦„λ‘œ ν‘œν˜„
    • νŠΉμ • 객체 μΈμŠ€ν„΄μŠ€λ©”μ„œλ“œ μ°Έμ‘°λŠ” μ°Έμ‘°λ³€μˆ˜::λ©”μ„œλ“œμ΄λ¦„μ™€ 같은 λ°©μ‹μœΌλ‘œ ν‘œν˜„

μƒμ„±μžμ˜ λ©”μ„œλ“œ μ°Έμ‘°

  • ν΄λž˜μŠ€μ΄λ¦„::new와 같은 λ°©μ‹μœΌλ‘œ ν‘œν˜„
  • λ°°μ—΄μ˜ κ²½μš°μ—” μžλ£Œν˜•[]::new와 같은 λ°©μ‹μœΌλ‘œ ν‘œν˜„

2. 슀트림(stream)

2.1 μŠ€νŠΈλ¦Όμ΄λž€?

  • forλ¬Έκ³Ό Iterator의 단점
    • μ½”λ“œκ°€ κΈΈλ‹€.
    • μ•Œμ•„λ³΄κΈ° 어렀움
    • μž¬μ‚¬μš©μ„± 떨어짐
    • 데이터 μ†ŒμŠ€λ§ˆλ‹€ λ‹€λ₯Έ λ°©μ‹μœΌλ‘œ 닀뀄야 함
  • μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μŠ€νŠΈλ¦Όμ„ λ§Œλ“¦
    • 데이터 μ†ŒμŠ€λ₯Ό 좔상화
    • μ»¬λ ‰μ…˜, νŒŒμΌμ— μ €μž₯된 데이터λ₯Ό λͺ¨λ‘ 같은 λ°©μ‹μœΌλ‘œ λ‹€λ£Έ

μŠ€νŠΈλ¦Όμ€ 데이터 μ†ŒμŠ€λ₯Ό λ³€κ²½ν•˜μ§€ μ•ŠλŠ”λ‹€.

  • 데이터λ₯Ό 읽기만 ν•  뿐 λ³€κ²½ X
  • λ³€κ²½ ν•„μš”μ‹œ κ²°κ³Όλ₯Ό μ»¬λ ‰μ…˜, λ°°μ—΄ 등에 ν• λ‹Ή

μŠ€νŠΈλ¦Όμ€ μΌνšŒμš©μ΄λ‹€.

  • μŠ€νŠΈλ¦Όμ€ Iterator처럼 일회용
  • ν•œλ²ˆ μ‚¬μš©ν•˜λ©΄ λ‹«ν˜€μ„œ λ‹€μ‹œ μ‚¬μš© λΆˆκ°€
  • μž¬μ‚¬μš© ν•„μš”μ‹œ μž¬μƒμ„±

μŠ€νŠΈλ¦Όμ€ μž‘μ—…μ„ λ‚΄λΆ€ 반볡으둜 μ²˜λ¦¬ν•œλ‹€.

  • λ‚΄λΆ€ λ°˜λ³΅μ΄λΌλŠ” 것은 λ°˜λ³΅λ¬Έμ„ λ©”μ„œλ“œμ˜ 내뢀에 숨길 수 μžˆλ‹€λŠ” 의미
  • forEach()λŠ” λ©”μ„œλ“œ μ•ˆμœΌλ‘œ for문을 넣은 것

슀트림의 μ—°μ‚°

  • 쀑간 μ—°μ‚°
    • μ—°μ‚° κ²°κ³Όκ°€ 슀트림
    • μ—°μ†ν•΄μ„œ 쀑간 μ—°μ‚° κ°€λŠ₯
  • μ΅œμ’… μ—°μ‚°
    • μ—°μ‚° κ²°κ³Όκ°€ 슀트림이 μ•„λ‹Œ μ—°μ‚°
    • 슀트림의 μš”μ†Œλ₯Ό μ†Œλͺ¨ν•˜λ―€λ‘œ 단 ν•œ 번만 κ°€λŠ₯

μ§€μ—°λœ μ—°μ‚°

  • μŠ€νŠΈλ¦Όμ€ μ΅œμ’… 연산이 μˆ˜ν–‰λ˜κΈ° μ „κΉŒμ§€ 쀑간 연산이 μˆ˜ν–‰ X
  • μ΅œμ’… 연산이 μˆ˜ν–‰λ˜μ–΄μ•Ό 슀트림의 μš”μ†Œλ“€μ΄ 쀑간 연산을 거쳐 μ΅œμ’… μ—°μ‚°μ—μ„œ μ†Œλͺ¨

Stream<Integer>와 IntStream

  • μ˜€ν† λ°•μ‹±&μ–Έλ°•μ‹±μœΌλ‘œ μΈν•œ λΉ„νš¨μœ¨μ„ 쀄이기 μœ„ν•΄ κΈ°λ³Έν˜•μœΌλ‘œ 데이터 μ†ŒμŠ€μ˜ μš”μ†Œλ₯Ό λ‹€λ£¨λŠ” μŠ€νŠΈλ¦Όλ„ 제곡
  • IntStream, LongStream, DoubleStream 제곡

병렬 슀트림

  • λ‚΄λΆ€μ μœΌλ‘œ fork&join ν”„λ ˆμž„μ›μ„ μ΄μš©ν•΄μ„œ μžλ™μ μœΌλ‘œ 연산을 λ³‘λ ¬λ‘œ μˆ˜ν–‰
  • parallel()을 ν˜ΈμΆœν•˜λ©΄ λ³‘λ ¬λ‘œ 연산을 μˆ˜ν–‰ν•˜λ„λ‘ μ§€μ‹œν•  수 있음
  • λ³‘λ ¬λ‘œ μ²˜λ¦¬λ˜μ§€ μ•Šκ²Œ ν•˜λ €λ©΄ sequential() 호좜
  • λͺ¨λ“  μŠ€νŠΈλ¦Όμ€ 기본적으둜 병렬 슀트림이 μ•„λ‹˜
  • λ³‘λ ¬μ²˜λ¦¬κ°€ 항상 더 λΉ λ₯Έ κ²°κ³Όλ₯Ό μ–»κ²Œ ν•΄μ£ΌλŠ” 것은 μ•„λ‹˜

2.2 슀트림 λ§Œλ“€κΈ°

μ»¬λ ‰μ…˜

  • Stream<T> Collection.stream() μ‚¬μš©

λ°°μ—΄

  • Stream<T> Stream.of(~) λ©”μ„œλ“œλ‘œ 슀트림 생성
  • int λ“±μ˜ κΈ°λ³Έν˜•μ€ IntStream IntStream.of(~) λ©”μ„œλ“œλ‘œ 생성

νŠΉμ • λ²”μœ„μ˜ μ •μˆ˜

  • IntStream, LongStream이 κ°–κ³  μžˆλŠ” λ©”μ„œλ“œ
  • μ—°μ†λœ μ •μˆ˜μ˜ μŠ€νŠΈλ¦Όμ„ 생성 ν›„ λ°˜ν™˜
  • IntStream.range(int begin, int end)
    • end κ°’ 미포함
  • IntStream.rangeClosed(int begin, int end)
    • end κ°’ 포함

μž„μ˜μ˜ 수

  • Random ν΄λž˜μŠ€μ—μ„œ μ œκ³΅ν•˜λŠ” λ‚œμˆ˜λ₯Ό μƒμ„±ν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” λ©”μ„œλ“œ
  • Intstream ints(), LongStream longs(), DoubleStream doubles()
  • 크기가 정해지지 μ•Šμ€ λ¬΄ν•œ μŠ€νŠΈλ¦Όμ„ λ°˜ν™˜
    • limit()을 같이 μ‚¬μš©ν•˜μ—¬ 크기λ₯Ό μ œν•œν•΄ 쀄 것
  • λ§€κ°œλ³€μˆ˜λ‘œ λ²”μœ„λ₯Ό 지정할 수 있음 (end κ°’ 미포함)

λžŒλ‹€μ‹ - iterate(), generate()

  • λžŒλ‹€μ‹μ„ λ§€κ°œλ³€μˆ˜λ‘œ λ°›μ•„μ„œ κ³„μ‚°λ˜λŠ” 값듀을 μš”μ†Œλ‘œ ν•˜λŠ” λ¬΄ν•œ 슀트림 생성
  • iterateλŠ” 씨앗 κ°’μœΌλ‘œ μ§€μ •λœ κ°’λΆ€ν„° μ‹œμž‘, λžŒλ‹€μ‹μ— μ˜ν•΄ κ³„μ‚°λœ κ²°κ³Όλ₯Ό λ‹€μ‹œ seed κ°’μœΌλ‘œ ν•΄μ„œ 계산 반볡
  • generateλŠ” λ§€κ°œλ³€μˆ˜κ°€ μ—†λŠ” λžŒλ‹€μ‹(Supplier)만 ν—ˆμš©ν•˜κΈ° λ•Œλ¬Έμ—, 이전 κ°’μœΌλ‘œ 계산 X
  • λ‘˜μ— μ˜ν•΄ μƒμ„±λœ μŠ€νŠΈλ¦Όμ„ κΈ°λ³Έν˜• νƒ€μž…μ˜ μ°Έμ‘° λ³€μˆ˜λ‘œ 닀루기 μœ„ν•΄μ„  mapToInt()와 같은 λ³€ν™˜ λ©”μ„œλ“œ ν•„μš”
    • λ°˜λŒ€λŠ” boxed() λ©”μ„œλ“œ μ‚¬μš©

파일

  • java.nio.file.Filesμ—μ„œ μ§€μ •λœ 디렉터리에 μžˆλŠ” 파일의 λͺ©λ‘μ„ μ†ŒμŠ€λ‘œ ν•˜λŠ” μŠ€νŠΈλ¦Όμ„ 생성 ν›„ λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œ 지원
  • Stream<Path> File.list(Path dir)
  • 파일의 ν•œ 행을 μš”μ†Œλ‘œ ν•˜λŠ” 슀트림 생성 λ©”μ„œλ“œλ„ 쑴재
    • Files.lines(~)

빈 슀트림

  • μš”μ†Œκ°€ λΉ„μ–΄μžˆλŠ” 슀트림 생성 μ‹œ null 보단 Stream.empty()λ₯Ό μ‚¬μš©ν•΄μ„œ λ§Œλ“€ 것
  • null을 할당해도 였λ₯˜λŠ” μ•„λ‹ˆλ‹€.

두 슀트림의 μ—°κ²°

  • 같은 νƒ€μž…μ˜ 두 μŠ€νŠΈλ¦Όμ„ concat()으둜 μ—°κ²°ν•  수 μžˆλ‹€.

2.3 슀트림의 쀑간 μ—°μ‚°

슀트림 자λ₯΄κΈ° - skip(), limit()

  • skip()은 μš”μ†Œλ₯Ό κ±΄λ„ˆ λœ€
  • limit은 슀트림의 μš”μ†Œλ₯Ό μ œν•œ(μž˜λΌλƒ„)
  • κΈ°λ³Έν˜• μŠ€νŠΈλ¦Όμ—λ„ μ •μ˜λ˜μ–΄ 있음

슀트림 μš”μ†Œ κ±ΈλŸ¬λ‚΄κΈ° - filter(), distinct()

  • filter()λŠ” 주어진 쑰건(Predicate)에 λ§žμ§€ μ•ŠλŠ” μš”μ†Œλ₯Ό κ±ΈλŸ¬λƒ„
    • μ—°μ‚° κ²°κ³Όκ°€ boolean인 λžŒλ‹€μ‹μ„ μ‚¬μš©ν•΄λ„ λœλ‹€.
    • ν•„μš”ν•˜λ‹€λ©΄ filter()λ₯Ό λ‹€λ₯Έ 쑰건으둜 μ—¬λŸ¬ 번 μ‚¬μš© κ°€λŠ₯
  • distinct()λŠ” μ€‘λ³΅λœ μš”μ†Œλ₯Ό 제거

μ •λ ¬ - sorted()

  • sort()λŠ” μ§€μ •λœ Comparator둜 μŠ€νŠΈλ¦Όμ„ μ •λ ¬
    • Comparator λŒ€μ‹  int 값을 λ°˜ν™˜ν•˜λŠ” λžŒλ‹€μ‹ μ‚¬μš© κ°€λŠ₯
  • Comparatorκ°€ μ§€μ •λ˜μ–΄ μžˆμ§€ μ•ŠμœΌλ©΄ 슀트림 μš”μ†Œμ˜ κΈ°λ³Έ μ •λ ¬ κΈ°μ€€(Comparable)둜 μ •λ ¬
    • JDK 1.8λΆ€ν„° Comparator μΈν„°νŽ˜μ΄μŠ€μ— static λ©”μ„œλ“œμ™€ λ””ν΄νŠΈ λ©”μ„œλ“œκ°€ 많이 μΆ”κ°€
    • 비ꡐ λŒ€μƒμ΄ κΈ°λ³Έν˜•μΈ 경우 thenComparing()이 효율적

λ³€ν™˜ - map()

  • μ›ν•˜λŠ” ν•„λ“œλ§Œ λ½‘μ•„λ‚΄κ±°λ‚˜ νŠΉμ • ν˜•νƒœλ‘œ λ³€ν™˜ν•΄μ•Ό ν•  λ•Œ μ‚¬μš©
  • T νƒ€μž…μ„ R νƒ€μž…μœΌλ‘œ λ³€ν™˜ν•΄μ„œ λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜λ₯Ό 지정해야 함
  • ν•˜λ‚˜μ˜ μŠ€νŠΈλ¦Όμ— μ—¬λŸ¬ 번 적용 κ°€λŠ₯

쑰회 - peek()

  • μ—°μ‚°κ³Ό μ—°μ‚° 사이에 μ˜¬λ°”λ₯΄κ²Œ μ²˜λ¦¬λ˜μ—ˆλŠ”μ§€ 확인할 λ•Œ μ‚¬μš©
  • forEachμ™€λŠ” 달리 슀트림 μš”μ†Œ μ†Œλͺ¨ X

mapToInt(), mapToLong(), mapToDouble()

  • Stream<T> νƒ€μž…μ˜ μŠ€νŠΈλ¦Όμ„ κΈ°λ³Έν˜• 슀트림으둜 λ³€ν™˜ν•  λ•Œ μ‚¬μš©ν•˜λŠ” λ©”μ„œλ“œλ“€
  • κΈ°λ³Έν˜•λ§Œ λ‹€λ£° 땐 μ—°μ‚° μ‹œ λ”°λ‘œ κΈ°λ³Έν˜•μœΌλ‘œ λ³€ν™˜ν•  ν•„μš”κ°€ μ—†μœΌλ―€λ‘œ 효율적
  • Stream<T> 보닀 숫자λ₯Ό λ‹€λ£¨λŠ”λ° νŽΈλ¦¬ν•œ λ©”μ„œλ“œλ“€μ„ 더 μ œκ³΅ν•¨
    • sum(), average(), max(), min()
    • 이 λ©”μ„œλ“œλ“€μ€ μ΅œμ’… 연산이기 λ•Œλ¬Έμ— 호좜 ν›„ 슀트림이 λ‹«νž˜
    • μŠ€νŠΈλ¦Όμ„ λ‹€μ‹œ 생성해야 ν•˜λŠ” λΆˆνŽΈν•¨μ„ 덜기 μœ„ν•΄ summaryStatistics() λ©”μ„œλ“œ 제곡
  • mapToObj() : κΈ°λ³Έν˜• μŠ€νŠΈλ¦Όμ„ Stream<T>으둜 λ³€ν™˜
  • boxed() : IntStream을 Stream<Integer>둜 λ³€ν™˜

flatMap() - Stream<T[]>λ₯Ό Stream<T>둜 λ³€ν™˜

  • 슀트림의 μš”μ†Œλ‚˜ map()의 μ—°μ‚° κ²°κ³Όκ°€ 배열일 경우 Stream<T>둜 λ³€ν™˜ν•˜κΈ° μœ„ν•΄ flatMap() μ‚¬μš©
    • flatMap()은 슀트림의 슀트림이 μ•„λ‹Œ 슀트림으둜 λ§Œλ“€μ–΄μ€€λ‹€.
  • 슀트림의 μŠ€νŠΈλ¦Όμ„ ν•˜λ‚˜μ˜ 슀트림으둜 ν•©μΉ  λ•Œλ„ flatMap() μ‚¬μš©

2.4 Optional<T>κ³Ό OptionalInt

  • Optional<T>λŠ” 지넀릭 클래슀둜 T νƒ€μž…μ˜ 객체λ₯Ό κ°μ‹ΈλŠ” 래퍼 클래슀
    • Optional νƒ€μž…μ˜ κ°μ²΄μ—λŠ” λͺ¨λ“  νƒ€μž…μ˜ μ°Έμ‘° λ³€μˆ˜λ₯Ό 담을 수 있음
    • private final T value ν•„λ“œλ₯Ό class λ‚΄λΆ€μ—μ„œ 가지고 있음
  • λ°˜ν™˜λœ κ²°κ³Όκ°€ null 인지 if문으둜 μ²΄ν¬ν•˜λŠ” λŒ€μ‹  Optional에 μ •μ˜λœ λ©”μ„œλ“œλ‘œ 처리 κ°€λŠ₯

Optional 객체 μƒμ„±ν•˜κΈ°

  • of() λ˜λŠ” ofNullable()을 μ‚¬μš©
    • μ°Έμ‘° λ³€μˆ˜μ˜ 값이 null 일 κ°€λŠ₯성이 있으면 ofNullable() μ‚¬μš©
    • null둜 μ΄ˆκΈ°ν™” ν•˜κΈ°λ³΄λ‹¨ empty()둜 μ΄ˆκΈ°ν™”ν•˜λŠ” 것이 λ°”λžŒμ§

Optional 객체의 κ°’ κ°€μ Έμ˜€κΈ°

  • Optional 객체의 값은 get()으둜 κ°€μ Έμ˜¬ 수 있음
    • null 일 λ•ŒλŠ” NoSuchElementException λ°œμƒ
  • μ˜ˆμ™Έλ₯Ό λŒ€λΉ„ν•΄μ„œ orElse()둜 λŒ€μ²΄ν•  κ°’ 지정 κ°€λŠ₯
    • orElseGet()으둜 null 값을 λŒ€μ²΄ν•  λžŒλ‹€μ‹ 지정 κ°€λŠ₯
    • orElseThrow()둜 null 일 λ•Œ μ§€μ •λœ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚¬ μˆ˜λ„ 있음
  • κ°’μ˜ 쑴재λ₯Ό 확인할 수 μžˆλŠ” isPresent() λ©”μ„œλ“œμ™€ 값이 μžˆμ„ λ•Œ μ‚¬μš©ν•  수 μžˆλŠ” ifPresent() λ©”μ„œλ“œ 쑴재
  • Stream ν΄λž˜μŠ€μ— μ •μ˜λœ λ©”μ„œλ“œ μ€‘μ—μ„œ Optional<T>을 λ°˜ν™˜ν•˜λŠ” 것듀이 쑴재
    • findAny(), findFirst(), max(), min(), reduce()

OptinalInt, OptionalLong, OptionalDouble

  • κΈ°λ³Έν˜•μ„ κ°’μœΌλ‘œ ν•˜λŠ” Optinalλ“€
  • IntStream 등에도 ν•΄λ‹Ή 클래슀λ₯Ό λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œ 쑴재
  • 기쑴의 get()이 getAsInt() λ“± λ©”μ„œλ“œ 이름이 μ‘°κΈˆμ”© 닀름
  • κΈ°λ³Έν˜• intκ°€ 0 일 λ•Œμ™€ μ•„λ¬΄λŸ° 값을 갖지 μ•ŠλŠ” 상황을 κ΅¬λ³„ν•˜κΈ° μœ„ν•΄ 클래슀 내뢀에 isPresentλΌλŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό 두고 ꡬ뢄

2.5 슀트림의 μ΅œμ’… μ—°μ‚°

  • μ΅œμ’… 연산은 슀트림의 μš”μ†Œλ₯Ό μ†Œλͺ¨ ν›„ κ²°κ³Όλ₯Ό λ§Œλ“€μ–΄λƒ„
  • μ΅œμ’… μ—°μ‚° ν›„μ—” 슀트림이 λ‹«νžˆκ³  더 이상 μ‚¬μš© λΆˆκ°€
  • μ΅œμ’… κ²°κ³ΌλŠ” 단일 κ°’μ΄κ±°λ‚˜ λ°°μ—΄ λ˜λŠ” μ»¬λ ‰μ…˜

forEach()

  • λ°˜ν™˜ νƒ€μž… void
  • 슀트림의 μš”μ†Œλ₯Ό 좜λ ₯ν•˜λŠ” λ“±μ˜ μš©λ„λ‘œ μ‚¬μš©

쑰건 검사 - allMatch(), anyMatch(), noneMatch(), findFirst(), findAny()

  • 슀트림의 μš”μ†Œμ— λŒ€ν•΄ μ§€μ •λœ 쑰건으둜 ν™•μΈν•˜λŠ” 데 μ‚¬μš©ν•  수 μžˆλŠ” λ©”μ„œλ“œλ“€
  • μ—°μ‚° 결과둜 boolean λ°˜ν™˜
  • findAny()와 findFirst()의 λ°˜ν™˜ νƒ€μž…μ€ Optional<T>
    • μš”μ†Œκ°€ 없을 μ‹œ λΉ„μ–΄μžˆλŠ” Optional 객체λ₯Ό λ°˜ν™˜

톡계 - count(), sum(), average(), max(), min()

  • 슀트림의 μš”μ†Œλ“€μ— λŒ€ν•œ 톡계 정보λ₯Ό 얻을 수 μžˆλŠ” λ©”μ„œλ“œλ“€
  • κΈ°λ³Έν˜•μ΄ 아닐 μ‹œμ—” count(), max(), min() μ„Έ 가지 λ©”μ„œλ“œλ“€λ§Œ μ‚¬μš© κ°€λŠ₯
    • μœ„μ˜ λ©”μ„œλ“œλ“€μ„ μ‚¬μš©ν•˜κΈ°λ³΄λ‹¨ κΈ°λ³Έν˜• 슀트림으둜 λ³€ν™˜ν•˜κ±°λ‚˜ reduce()와 collect()λ₯Ό μ‚¬μš©ν•΄μ„œ 톡계 정보λ₯Ό μ–»μŒ

리듀싱 - reduce()

  • 슀트림의 μš”μ†Œλ₯Ό μ€„μ—¬λ‚˜κ°€λ©΄μ„œ 연산을 μˆ˜ν–‰ν•œ λ’€ μ΅œμ’… κ²°κ³Όλ₯Ό λ°˜ν™˜
  • 처음 두 μš”μ†Œλ₯Ό 가지고 μ—°μ‚°ν•œ κ²°κ³Όλ₯Ό κ·Έλ‹€μŒ μš”μ†Œμ™€ μ—°μ‚°
    • λ§€κ°œλ³€μˆ˜μ˜ νƒ€μž… BinaryOperator<T>
  • λ§€κ°œλ³€μˆ˜κ°€ μ΄ˆκΈ°κ°’μ„ κ°–λŠ” reduce()λŠ” μ΄ˆκΈ°κ°’κ³Ό 슀트림의 첫 번째 μš”μ†Œλ‘œ 연산을 μ‹œμž‘
    • 슀트림의 μš”μ†Œκ°€ 없을 μ‹œ μ΄ˆκΈ°κ°’μ΄ λ°˜ν™˜
    • μ΄ˆκΈ°κ°’μ΄ μžˆμœΌλ―€λ‘œ λ°˜ν™˜ νƒ€μž…μ΄ Optional이 μ•„λ‹Œ T (초기 값이 μ—†λŠ” reduce λ©”μ„œλ“œλŠ” λ°˜ν™˜κ°’ Optional)
  • combiner λ§€κ°œλ³€μˆ˜λŠ” 병렬 μŠ€νŠΈλ¦Όμ— μ˜ν•΄ 처리된 κ²°κ³Όλ₯Ό ν•©μΉ  λ•Œ μ‚¬μš©ν•˜λŠ” λ§€κ°œλ³€μˆ˜

2.6 collect()

  • 슀트림의 μ΅œμ’… μ—°μ‚° 쀑 κ°€μž₯ λ³΅μž‘ν•˜λ©΄μ„œλ„ μœ μš©ν•˜κ²Œ ν™œμš©
  • 리듀싱과 μœ μ‚¬ν•œ 방식
  • collect()의 λ§€κ°œλ³€μˆ˜λ‘œ μ–΄λ–»κ²Œ μˆ˜μ§‘ν•  것인가에 λŒ€ν•œ 방법이 μ •μ˜λ˜μ–΄μ•Ό ν•˜λŠ”λ° κ·Έ 방법을 μ •μ˜ν•œ 것이 collector
  • collect()λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ μ•Œμ•„μ•Ό ν•˜λŠ” 것
    • collect() : 슀트림의 μ΅œμ’… μ—°μ‚°, λ§€κ°œλ³€μˆ˜λ‘œ 컬렉터λ₯Ό ν•„μš”λ‘œ 함
    • Collector : μΈν„°νŽ˜μ΄μŠ€, μ»¬λ ‰ν„°λŠ” 이 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ•Ό 함
    • Collectors : 클래슀, static λ©”μ„œλ“œλ‘œ 미리 μž‘μ„±λœ 컬렉터λ₯Ό 제곡
  • λ§€κ°œλ³€μˆ˜λ‘œ Collector κ΅¬ν˜„μ²΄κ°€ λ“€μ–΄κ°„ collect λ©”μ„œλ“œμ™€ Supplier, BiConsumer 두 κ°œκ°€ λ“€μ–΄κ°„ λ©”μ„œλ“œ 쑴재
    • 두 번째 λ©”μ„œλ“œλŠ” 잘 μ‚¬μš©λ˜μ§€ μ•ŠλŠ”λ‹€.

μŠ€νŠΈλ¦Όμ„ μ»¬λ ‰μ…˜κ³Ό λ°°μ—΄λ‘œ λ³€ν™˜ - toList(), toSet(), toMap(), toCollection, toArray()

  • ListλŠ” Collectors.toList() μ‚¬μš©
  • νŠΉμ • μ»¬λ ‰μ…˜μ€ toCollection()에 ν•΄λ‹Ή μ»¬λ ‰μ…˜μ˜ μƒμ„±μž μ°Έμ‘°λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ λ„£κΈ°
    • ex) ArrayList::new
  • Map의 κ²½μš°μ—” toMap λ©”μ„œλ“œμ˜ νŒŒλΌλ―Έν„°λ‘œ 킀와 값을 μ •ν•΄μ€˜μ•Ό 함
  • μŠ€νŠΈλ¦Όμ—μ„œ μ €μž₯된 μš”μ†Œλ“€μ„ λ°°μ—΄λ‘œ λ°˜ν™˜ν•˜λ €λ©΄ (stream μ°Έμ‘° λ³€μˆ˜).toArray() μ‚¬μš©
    • μ›ν•˜λŠ” νƒ€μž…μ˜ μƒμ„±μž μ°Έμ‘°λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ 지정
    • λ§€κ°œλ³€μˆ˜λ₯Ό μ§€μ •ν•˜μ§€ μ•Šμ„ μ‹œ λ°°μ—΄μ˜ νƒ€μž…μ€ Object[]

톡계 - counting(), summingInt(), averageInt(), maxBy(), minBy()

  • collect()κ°€ μ•„λ‹ˆμ–΄λ„ μœ„μ˜ μ—°μ‚°λ“€μ˜ κ²°κ³Όλ₯Ό 얻을 수 μžˆμ§€λ§Œ collect()λ₯Ό μ‚¬μš©ν•˜λ©΄ groupingBy()와 ν•¨κ»˜ μ‚¬μš© κ°€λŠ₯

리듀싱 - reducing()

  • collect()μ—μ„œ 리듀싱도 μ‚¬μš© κ°€λŠ₯
  • λ§€κ°œλ³€μˆ˜μ— 따라 3가지 μ’…λ₯˜κ°€ 있음

λ¬Έμžμ—΄ κ²°ν•© - joining()

  • λ¬Έμžμ—΄ 슀트림의 λͺ¨λ“  μš”μ†Œλ₯Ό ν•˜λ‚˜μ˜ λ¬Έμžμ—΄λ‘œ μ—°κ²°ν•΄μ„œ λ°˜ν™˜
  • κ΅¬λΆ„μžμ™€ 접두사, 접미사도 지정 κ°€λŠ₯

그룹화와 λΆ„ν•  - groupingBy(), partitioningBy()

  • 슀트림의 μš”μ†Œλ₯Ό νŠΉμ • κΈ°μ€€μœΌλ‘œ κ·Έλ£Ήν™”
  • groupingBy()λŠ” 슀트림의 μš”μ†Œλ₯Ό Function으둜 λΆ„λ₯˜
  • partitioningBy()λŠ” 슀트림의 μš”μ†Œλ₯Ό Predicate둜 λΆ„λ₯˜
    • μŠ€νŠΈλ¦Όμ„ 두 그룹으둜 λ‚˜λˆŒ λ•Œ groupingBy() 보닀 빠름

partitioningBy()에 μ˜ν•œ λΆ„λ₯˜

  • μ˜ˆμ‹œλ‘œ collect(Collectors.partitioningBy(Student::isMale)) κ³Ό 같은 λ°©μ‹μœΌλ‘œ 학생듀을 μ„±λ³„λ‘œ λΆ„ν• ν•  수 μžˆλ‹€.
    • Map<Boolean, List>의 return 값을 λ°›κ²Œ 되며 get(true)둜 쑰건에 λ§žλŠ” 학생 listλ₯Ό 얻을 수 μžˆλ‹€.
    • get(false)의 경우 쑰건에 λ§žμ§€ μ•ŠλŠ” 학생 (μœ„ μ˜ˆμ‹œλ‘œλŠ” 여학생)의 listλ₯Ό 얻을 수 μžˆλ‹€.
  • collect(Collectors.partitioningBy(Student::isMale, counting())) κ³Ό 같은 λ°©μ‹μœΌλ‘œ ν•™μƒμ˜ 수 μ—­μ‹œ ꡬ할 수 μžˆλ‹€.
  • 이외에도 두 번째 νŒŒλΌλ―Έν„°μ— maxBy, collectingAndThen, 또 λ‹€λ₯Έ partitioningBy() 등을 넣어쀄 수 μžˆλ‹€.
    • κ²½μš°μ— 따라 T μžμ²΄λ‚˜ Optionalλ₯Ό Map으둜 return 받을 수 있음

groupingBy()에 μ˜ν•œ λΆ„λ₯˜

  • groupingBy()둜 κ·Έλ£Ήν™” μ‹œ 기본적으둜 List에 값을 λ‹΄μŒ
    • ν•„μš”μ‹œ toList() λŒ€μ‹  toSet(), toCollection(HashSet::new)을 μ‚¬μš© κ°€λŠ₯ (Map은 지넀릭 νƒ€μž…λ„ 적절히 λ³€κ²½ν•΄ μ€˜μ•Ό 함)
  • groupingBy()을 μ—¬λŸ¬ 번 μ‚¬μš©ν•˜λ©΄ λ‹€μˆ˜μ€€ κ·Έλ£Ήν™”κ°€ κ°€λŠ₯함

2.7 Collector κ΅¬ν˜„ν•˜κΈ°

  • Collector μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ•Ό 함
  • characteristics()λ₯Ό μ œμ™Έν•œ 4개의 λžŒλ‹€μ‹μ„ μž‘μ„±ν•΄μ•Ό 함
    • supplier() : μž‘μ—… κ²°κ³Όλ₯Ό μ €μž₯ν•  곡간을 제곡
    • accumulator() : 슀트림의 μš”μ†Œλ₯Ό μˆ˜μ§‘ν•  방법 제곡
    • combiner() : 두 μ €μž₯ 곡간을 병합할 방법을 제곡 (병렬 슀트림)
    • finisher() : κ²°κ³Όλ₯Ό μ΅œμ’…μ μœΌλ‘œ λ³€ν™˜ν•  방법 제곡
  • characteristics()λŠ” 컬렉터가 μˆ˜ν–‰ν•˜λŠ” μž‘μ—…μ˜ 속성에 λŒ€ν•œ 정보λ₯Ό 제곡
    • Characteristics.CONCURRENT : λ³‘λ ¬λ‘œ μ²˜λ¦¬ν•  수 μžˆλŠ” μž‘μ—…
    • Characteristics.UNORDERED : 슀트림의 μš”μ†Œμ˜ μˆœμ„œκ°€ μœ μ§€λ  ν•„μš”κ°€ μ—†λŠ” μž‘μ—…
    • Characteristics.IDENTITY_FINISH : finisher()κ°€ ν•­λ“± ν•¨μˆ˜μΈ μž‘μ—…
    • μ•„λ¬΄λŸ° 속성도 μ§€μ •ν•˜κ³  싢지 μ•Šμ„ 땐 Collections.emptySet()을 return ν•˜λ„λ‘ κ΅¬ν˜„