moon101 2023. 1. 19. 03:30

Streams API

λ‹€λ₯Έ 객체λ₯Ό ν¬ν•¨ν•˜λŠ” μ»¬λ ‰μ…˜μ΄λΌλ„ μš°λ¦¬κ°€ μ–»κ³ μž ν•˜λŠ” μ •λ³΄λŠ” λΉ„μŠ·ν•  수 μžˆλ‹€.

예λ₯Ό λ“€μ–΄, 'μ΄λŸ¬ν•œ 쑰건에 λ§žλŠ” μ•„μ΄ν…œμ„ 쀘', 'μ΄λŸ¬ν•œ 방법을 ν™œμš©ν•΄μ„œ λͺ¨λ“  μ•„μ΄ν…œμ„ λ°”κΏ”μ€˜, ' 'μ€‘λ³΅λœ λ°μ΄ν„°λŠ” μ§€μ›Œμ€˜', λ˜λŠ” '이런 λ°©λ²•μœΌλ‘œ μš”μ†Œλ“€μ„ μ •λ ¬ν•΄ 쀘' 등을 μ»¬λ ‰μ…˜μ— μš”μ²­ν•œλ‹€κ³  생각해 보자. μš°λ¦¬λŠ” μ΄λŸ¬ν•œ μš”μ²­μ„ μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄ forλ¬Έκ³Ό Iteratorλ₯Ό μ΄μš©ν•΄μ„œ μ½”λ“œλ₯Ό μž‘μ„±ν•˜κ±°λ‚˜ 각 μ»¬λ ‰μ…˜ ν΄λž˜μŠ€μ— λ§žλŠ” λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄ μ™”λ‹€. Listλ₯Ό μ •λ ¬ν•  λ•ŒλŠ” Collections.sort()λ₯Ό μ‚¬μš©ν•˜κ³  배열을 μ •λ ¬ν•  λ•ŒλŠ” Arrays.sort()λ₯Ό μ‚¬μš©ν–ˆλ‹€. 

 

Streams APIλŠ” 데이터 μ†ŒμŠ€λ₯Ό 좔상화 ν•΄μ„œ 데이터 μ†ŒμŠ€κ°€ 무엇이든 같은 λ°©μ‹μœΌλ‘œ λ‹€λ£° 수 μžˆλŠ” λ©”μ†Œλ“œλ₯Ό μ œκ³΅ν•΄ μ€€λ‹€. κ·Έλž˜μ„œ μš°λ¦¬λŠ” 'μ–΄λ–»κ²Œ' λ³΄λ‹€λŠ” '무엇을'에 μ΄ˆμ μ„ 맞좰 μ»¬λ ‰μ…˜μ— Streams APIκ°€ μ œκ³΅ν•˜λŠ” 연산듀을 μ‚¬μš©ν•  수 μžˆλ‹€. 

 

Stream λ©”μ†Œλ“œμ—λŠ” 쀑간 μ—°μ‚°(intermediate operations)ν•˜κ³  μ΅œμ’… μ—°μ‚°(terminal operations)이 μžˆλŠ”λ° μ΅œμ’…μ—°μ‚°μ„ μ‚¬μš©ν•΄μ•Ό μ›ν•˜λŠ” κ²°κ³Ό(output)λ₯Ό 얻을 수 μžˆλ‹€. 쀑간 연산은 μ§€μ—°λœ μ—°μ‚°μœΌλ‘œ μ΅œμ’…μ—°μ‚°μ΄ μˆ˜ν–‰λ˜κΈ° μ „κΉŒμ§€λŠ” 쀑간 연산이 μˆ˜ν–‰λ˜μ§€ μ•ŠλŠ”λ‹€. 

  • 쀑간 μ—°μ‚°(lazy) : 슀트림 λ©”μ†Œλ“œλ‘œ λ‹€λ₯Έ μŠ€νŠΈλ¦Όμ„ λ°˜ν™˜ν•œλ‹€. μ΅œμ’… 연산을 ν˜ΈμΆœν•΄μ„œ κ²°κ³Όλ₯Ό 좜λ ₯ν•˜κΈ° μ „κΉŒμ§€ μŠ€νƒμ²˜λŸΌ 쀑간 연산을 계속 μ–Ήμ–΄μ„œ μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€. 쀑간 연산은 stateless ν•˜κ³  stateful둜 λ‚˜λˆŒ 수 μžˆλŠ”λ° λ§Œμ•½ 쀑간 연산이 연산을 ν•˜κΈ° μœ„ν•΄ 데이터 μ†ŒμŠ€μ˜ 정보λ₯Ό λͺ¨λ‘ μ•Œμ•„μ•Ό ν•œλ‹€λ©΄ κ·Έ 연산은 stateful ν•˜λ‹€κ³  ν•  수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄, filter()λŠ” stateless ν•˜κ³ , sorted()λŠ” stateful ν•˜λ‹€κ³  ν•  수 μžˆλ‹€.
    • 예) Stream<T> limit (long maxSize) : 슀트림의 일뢀λ₯Ό μž˜λΌλ‚Ό λ•Œ μ‚¬μš©. maxSize만큼 슀트림의 μš”μ†Œλ₯Ό μ œν•œν•œλ‹€. 
  • μ΅œμ’… μ—°μ‚°(eager) : 슀트림의 μš”μ†Œλ₯Ό μ†Œλͺ¨ν•΄μ„œ κ²°κ³Όλ₯Ό λ§Œλ“€μ–΄ λ‚Έλ‹€. μ΅œμ’… μ—°μ‚° ν›„μ—μ„œλŠ” 슀트림이 λ‹«νžˆκ³  더 이상 μ‚¬μš©ν•  수 μ—†λ‹€. 
    • 예) boolean anyMatch(Predicate<? super T> predicate) : returns true if any element matches the provided predicate

 

슀트림 μ˜€νΌλ ˆμ΄μ…˜μ„ μ‚¬μš©ν•˜λŠ” 방법(stream pipeline)은 3λ‹¨κ³„λ‘œ λ‚˜λˆŒ 수 있고, 이 쀑 1λ²ˆμ§Έμ™€ 3λ²ˆμ§ΈλŠ” κΌ­ ν•„μš”ν•˜λ‹€. 

  1. μ»¬λ ‰μ…˜μ„ μŠ€νŠΈλ¦Όν™”ν•˜κΈ° 
  2. λ§Œλ“€μ–΄μ€€ μŠ€νŠΈλ¦Όμ— 쀑간 μ—°μ‚° μ‚¬μš© 
  3. 결과물을 μ΅œμ’…μ—°μ‚°μ„ μ‚¬μš©ν•΄μ„œ κ°€μ Έμ˜€κΈ°

 

슀트림의 νŠΉμ§•μ€ λ‹€μŒκ³Ό κ°™λ‹€. 

  • μž¬μ‚¬μš©μ΄ λΆˆκ°€λŠ₯ν•˜λ‹€. λ§Œμ•½ μŠ€νŠΈλ¦Όμ„ λ³€μˆ˜μ— μ €μž₯ν•΄ 놓고 μž¬μ‚¬μš©ν•˜λ €κ³  ν•˜λ©΄ exception이 λ°œμƒν•œλ‹€. 
  • 슀트림이 λ™μž‘ν•˜λŠ” λ™μ•ˆμ—λŠ” μ»¬λ ‰μ…˜μ„ λ³€κ²½ν•  수 μ—†λ‹€.
  • 슀트림 연산은 원본 μ»¬λ ‰μ…˜μ„ λ³€κ²½ν•˜μ§€ μ•ŠλŠ”λ‹€. 

 

였브젝트 5μž₯ν•˜κ³  12μž₯에 슀트림이 λ‚˜μ™€μ„œ TODO둜 적어놓고 λ„˜μ–΄κ°”λ˜ μ½”λ“œλ₯Ό κ°€μ Έμ™”λ‹€. 

  • 5μž₯ μ½”λ“œ

λžŒλ‹€μ‹μ€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œλ‹€. κ·Έλž˜μ„œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ‘œ λžŒλ‹€μ‹μ„ μ°Έμ‘°ν•  수 μžˆλ‹€.

  • 12μž₯ μ½”λ“œ

mapToInt()와 자주 μ‚¬μš©λ˜λŠ” λ©”μ„œλ“œλ‘œλŠ” Integer의 parseInt()λ‚˜ valueOf()κ°€ μžˆλ‹€.
Collections.unmodifiableList()

 

 

Lambda

λžŒλ‹€μ‹μ„ 잘 μ΄ν•΄ν•˜λ©΄ Stream APIλ₯Ό 더 μ‰½κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€. λžŒλ‹€μ‹μ€ 객체이고, single abstract method을 ν˜ΈμΆœν•΄μ„œ μ‚¬μš©ν•œλ‹€. λžŒλ‹€μ‹μ€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€(functional interface)λ₯Ό κ΅¬ν˜„ν•˜κ³  있고 ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ—λŠ” 였직 ν•˜λ‚˜μ˜ 좔상 λ©”μ„œλ“œλ§Œ μ •μ˜λ˜μ–΄ μžˆμ–΄μ•Ό ν•œλ‹€. (static λ©”μ„œλ“œμ™€ default λ©”μ„œλ“œμ˜ κ°œμˆ˜λŠ” μƒκ΄€μ—†μŒ) 읡λͺ… λ‚΄λΆ€ ν΄λž˜μŠ€μ™€ λΉ„μŠ·ν•¨. 

 

ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€

  • BinaryOperator<T> : method apply T νƒ€μž…μ˜ 인자 2개λ₯Ό λ°›μ•„μ„œ T νƒ€μž…μ˜ 값을 λ°˜ν™˜ν•¨ 
  • Consumer<T> : method accept  T νƒ€μž…μ˜ 인자λ₯Ό λ°›κ³ , λ°˜ν™˜κ°’μ€ μ—†μŒ
  • Function<T, R> : method apply T νƒ€μž…μ˜ 인자λ₯Ό λ°›μ•„μ„œ R νƒ€μž…μ˜ 값을 λ°˜ν™˜ν•¨
  • Predicate<T> : method test T νƒ€μž…μ˜ 인자λ₯Ό λ°›μ•„μ„œ boolean을 λ°˜ν™˜ν•¨
  • Supplier<T> : method get 인자λ₯Ό λ°›μ§€ μ•Šκ³ , T νƒ€μž…μ˜ 값을 λ°˜ν™˜ν•¨. μŠ€νŠΈλ¦Όμ—μ„œ μ—°μ‚°μ˜ κ²°κ³Όλ₯Ό μ €μž₯ν•  μ»¬λ ‰μ…˜ 객체λ₯Ό μƒμ„±ν•˜λŠ” 데 주둜 μ‚¬μš©λ¨
  • UnaryOperator<T> : method get 인자λ₯Ό λ°›μ§€ μ•Šκ³ , T νƒ€μž…μ˜ 값을 λ°˜ν™˜ν•¨
Stream<T> filter(Predicate<? super T>predicate)
	Returns a stream of the elements that match the given predicate.
    
<T> : the Type of the object in the stream
<R> : the type of the Result of the method

 

μ—¬κΈ°μ„œ <? super T>λŠ” μ™€μΌλ“œ μΉ΄λ“œμΈλ° μ—¬κΈ°μ„œμ˜ TλŠ” lower bound이고,

<? extends T>μ—μ„œμ˜ TλŠ” upper bound이닀. 

예λ₯Ό λ“€λ©΄, List<? super Integer>이면 List<Integer>, List<Number>, 그리고 List<Object>κ°€ λ“€μ–΄κ°ˆ 수 μžˆλ‹€. 

 

 

λžŒλ‹€μ‹μ„ 더 κ°„λ‹¨ν•˜κ²Œ ν‘œν˜„ν•  수 μžˆλŠ” λ°©λ²•μœΌλ‘œλŠ” λ©”μ„œλ“œ μ°Έμ‘° (method reference)κ°€ μžˆλŠ”λ°,

ν•˜λ‚˜μ˜ λ©”μ„œλ“œλ§Œ ν˜ΈμΆœν•˜λŠ” λžŒλ‹€μ‹μ€ '클래슀 이름::λ©”μ„œλ“œμ΄λ¦„' λ˜λŠ” 'μ°Έμ‘°λ³€μˆ˜::λ©”μ„œλ“œμ΄λ¦„'으둜 λ°”κΏ€ 수 μžˆλ‹€. 

 

λ©”μ„œλ“œ μ°Έμ‘°μ—λŠ” 4κ°€μ§€ νƒ€μž…μ΄ μžˆλ‹€. 

  • instance method => String::toUpperCase String 클래슀의 toUpperCase λ©”μ†Œλ“œ 호좜
String::toUpperCase String 클래슀의 toUpperCase λ©”μ†Œλ“œ 호좜
μ•„λž˜ 두 개의 λžŒλ‹€μ‹μ„ λ©”μ„œλ“œ 참쑰둜 λ°”κΎΌ 것.
(String s) -> {return s.toUpperCase();}
s -> s.toUpperCase()
  • instance method of specific object => System.out::println
  • static method => Math::sqrt
  • constructor => TreeMap::new κΈ°λ³Έ μƒμ„±μž(μΈμžκ°€ μ—†λŠ”)λ₯Ό ν˜ΈμΆœν•΄μ„œ 객체λ₯Ό 생성할 λ•Œ μ‚¬μš©

 

 

μžλ°” 8μ—μ„œ λžŒλ‹€μ™€ 슀트림이 μΆ”κ°€λ˜λ©΄μ„œ functional programming이 κ°€λŠ₯ν•΄μ‘Œκ³ , 

λ³€μˆ˜λ“€μ΄ immutable ν•˜κΈ° λ•Œλ¬Έμ— λŸ°νƒ€μž„μ‹œμ— 데이터에 λ¬Έμ œκ°€ 생길 ν™•λ₯ μ΄ 쀄어듀어 λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ λ³‘λ ¬μ²˜λ¦¬ν•˜λŠ” 것을 μ’€ 더 μ‰½κ²Œ λ§Œλ“€μ–΄ μ€€λ‹€.

 

 

// TODO

λ©€ν‹°μŠ€λ ˆλ“œ 뢀뢄은 아직 κ³΅λΆ€ν•˜μ§€ μ•Šμ•˜λŠ”λ°, λ‚˜μ€‘μ— μ™œ μ΄λ ‡κ²Œ λ˜λŠ”μ§€ 찾아봐야겠닀. 

 

 

 

 

 

참고자료

ν—€λ“œνΌμŠ€νŠΈ μžλ°” ch.12

μžλ°”μ˜ 정석 ch.14

μŠ€ν”„λ§ μž…λ¬Έμ„ μœ„ν•œ μžλ°” 객체 μ§€ν–₯의 원리와 이해 뢀둝 B.

https://learning.oreilly.com/videos/java-8-fundamentals/9780133489354/9780133489354-JFUN_lesson17_02/

https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html

https://docs.oracle.com/javase/tutorial/extra/generics/morefun.html

https://stackoverflow.com/questions/2827585/what-is-super-t-syntax

https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html