etc/java

πŸ’«λžŒλ‹€μ‹ & Stream API

sh119 2024. 8. 21. 12:04

1. λžŒλ‹€μ‹ (Lambda Expression)

λžŒλ‹€μ‹μ€ μžλ°” 8μ—μ„œ λ„μž…λœ κΈ°λŠ₯으둜, μ½”λ“œλ₯Ό 더 κ°„κ²°ν•˜κ³  읽기 μ‰½κ²Œ λ§Œλ“€μ–΄μ€€λ‹€. κΈ°μ‘΄μ—λŠ” 읡λͺ… 클래슀λ₯Ό μ‚¬μš©ν•˜μ—¬ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν–ˆμ§€λ§Œ, λžŒλ‹€μ‹μ„ μ‚¬μš©ν•˜λ©΄ 이λ₯Ό 훨씬 κ°„λ‹¨ν•˜κ²Œ ν‘œν˜„ν•  수 μžˆλ‹€.

1.1 λžŒλ‹€μ‹μ˜ 문법

λžŒλ‹€μ‹μ€ λ§€κ°œλ³€μˆ˜ λͺ©λ‘κ³Ό ν™”μ‚΄ν‘œ(->), 그리고 μ‹€ν–‰ν•  μ½”λ“œλ₯Ό ν•œ μ€„λ‘œ ν‘œν˜„ν•œλ‹€. 예λ₯Ό λ“€μ–΄, λ‹€μŒκ³Ό 같은 ν˜•νƒœλ‘œ μž‘μ„±ν•˜κ²Œ λœλ‹€:

(parameters) -> expression

ν˜Ήμ€ μ‹€ν–‰ν•  μ½”λ“œκ°€ μ—¬λŸ¬ 쀄이라면 μ€‘κ΄„ν˜Έλ‘œ λ¬Άμ–΄μ€€λ‹€:

 
(parameters) -> { 
	// μ—¬λŸ¬ μ€„μ˜ μ½”λ“œ 
    }

λžŒλ‹€μ‹μ€ 주둜 ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ™€ ν•¨κ»˜ μ‚¬μš©λœλ‹€. ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λŠ” ν•˜λ‚˜μ˜ 좔상 λ©”μ„œλ“œλ§Œ κ°€μ§€λŠ” μΈν„°νŽ˜μ΄μŠ€λ‘œ, @FunctionalInterface μ–΄λ…Έν…Œμ΄μ…˜μœΌλ‘œ λͺ…μ‹œν•  수 μžˆλ‹€. λŒ€ν‘œμ μΈ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ‘œλŠ” Runnable, Callable, Comparator, 그리고 Function 등이 μžˆλ‹€.

1.2 λžŒλ‹€μ‹μ˜ 예제

λžŒλ‹€μ‹μ„ μ‚¬μš©ν•˜μ—¬ 리슀트의 μš”μ†Œλ₯Ό 좜λ ₯ν•˜λŠ” 예제λ₯Ό 보자. κΈ°μ‘΄μ—λŠ” μ΄λ ‡κ²Œ μž‘μ„±ν•˜λ˜ μ½”λ“œλ₯Ό:

List<String> list = Arrays.asList("apple", "banana", "cherry"); 
for (String s : list) { 
	System.out.println(s); 
}

λžŒλ‹€μ‹μ„ μ‚¬μš©ν•˜μ—¬ λ‹€μŒκ³Ό 같이 κ°„λ‹¨ν•˜κ²Œ μž‘μ„±ν•  수 μžˆλ‹€:

list.forEach(s -> System.out.println(s));

이처럼 λžŒλ‹€μ‹μ„ μ‚¬μš©ν•˜λ©΄ μ½”λ“œκ°€ 훨씬 κ°„κ²°ν•΄μ§€κ³ , 가독성도 λ†’μ•„μ§„λ‹€.

2. 슀트림 API (Stream API)

슀트림 APIλŠ” μžλ°” μ»¬λ ‰μ…˜μ— λŒ€ν•΄ λ³΅μž‘ν•œ 데이터 처리 μž‘μ—…μ„ μ‰½κ²Œ μˆ˜ν–‰ν•  수 μžˆλ„λ‘ λ„μ™€μ£ΌλŠ” κΈ°λŠ₯이닀. μŠ€νŠΈλ¦Όμ„ μ‚¬μš©ν•˜λ©΄ 데이터 μ†ŒμŠ€λ₯Ό μΆ”μƒν™”ν•˜κ³ , 필터링, λ§€ν•‘, μ •λ ¬ λ“±μ˜ μž‘μ—…μ„ μ„ μ–Έμ μœΌλ‘œ μž‘μ„±ν•  수 μžˆλ‹€.

2.1 슀트림 API의 μ£Όμš” νŠΉμ§•

  • 선언적 방식: 슀트림 APIλ₯Ό μ‚¬μš©ν•˜λ©΄ 데이터λ₯Ό μ²˜λ¦¬ν•˜λŠ” 방식을 μ½”λ“œλ‘œ μ„€λͺ…ν•˜λŠ” 것이 μ•„λ‹ˆλΌ, 무엇을 ν•  것인지에 μ΄ˆμ μ„ 맞좜 수 μžˆλ‹€.
  • 체이닝: μ—¬λŸ¬ 슀트림 연산을 μ—°κ²°ν•˜μ—¬ ν•œ μ€„μ˜ μ½”λ“œλ‘œ λ³΅μž‘ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆλ‹€.
  • λ‚΄λΆ€ 반볡: 기쑴의 for-each λ¬Έκ³Ό 달리 μŠ€νŠΈλ¦Όμ€ λ‚΄λΆ€μ μœΌλ‘œ λ°˜λ³΅μ„ μ²˜λ¦¬ν•˜λ―€λ‘œ, λ©€ν‹°μ½”μ–΄ ν”„λ‘œμ„Έμ„œλ₯Ό ν™œμš©ν•œ 병렬 μ²˜λ¦¬λ„ κ°€λŠ₯ν•˜λ‹€.

2.2 슀트림 API의 μ‚¬μš© 예제

λ¦¬μŠ€νŠΈμ—μ„œ νŠΉμ • 쑰건을 λ§Œμ‘±ν•˜λŠ” μš”μ†Œλ§Œ ν•„ν„°λ§ν•œ ν›„, 각 μš”μ†Œλ₯Ό λ³€ν™˜ν•˜κ³ , κ·Έ κ²°κ³Όλ₯Ό μˆ˜μ§‘ν•˜λŠ” μž‘μ—…μ„ μŠ€νŠΈλ¦Όμ„ 톡해 κ°„λ‹¨ν•˜κ²Œ μˆ˜ν–‰ν•  수 μžˆλ‹€:

List<String> list = Arrays.asList("apple", "banana", "cherry"); 
List<String> filteredList = list.stream() 
								.filter(s -> s.startsWith("a")) // 'a'둜 μ‹œμž‘ν•˜λŠ” μš”μ†Œλ§Œ 필터링 
                                .map(String::toUpperCase) // λŒ€λ¬Έμžλ‘œ λ³€ν™˜ 
                                .collect(Collectors.toList()); // κ²°κ³Όλ₯Ό 리슀트둜 μˆ˜μ§‘
                                
System.out.println(filteredList); // [APPLE]

이 μ½”λ“œλŠ” 리슀트의 각 μš”μ†Œλ₯Ό 슀트림으둜 μ²˜λ¦¬ν•˜λ©΄μ„œ, νŠΉμ • 쑰건을 λ§Œμ‘±ν•˜λŠ” μš”μ†Œλ§Œ ν•„ν„°λ§ν•˜κ³ , λŒ€λ¬Έμžλ‘œ λ³€ν™˜ν•œ ν›„ κ²°κ³Όλ₯Ό 리슀트둜 μˆ˜μ§‘ν•œλ‹€.

2.3 슀트림 API의 μ£Όμš” μ—°μ‚°

  • filter(Predicate): μ£Όμ–΄μ§„ 쑰건에 λ§žλŠ” μš”μ†Œλ§Œ ν•„ν„°λ§ν•œλ‹€.
  • map(Function): 각 μš”μ†Œλ₯Ό μ£Όμ–΄μ§„ ν•¨μˆ˜μ— 따라 λ³€ν™˜ν•œλ‹€.
  • sorted(): μš”μ†Œλ₯Ό μ •λ ¬ν•œλ‹€.
  • collect(Collector): 슀트림의 κ²°κ³Όλ₯Ό νŠΉμ • 자료ꡬ쑰둜 μˆ˜μ§‘ν•œλ‹€.
  • forEach(Consumer): 각 μš”μ†Œμ— λŒ€ν•΄ μ£Όμ–΄μ§„ μž‘μ—…μ„ μˆ˜ν–‰ν•œλ‹€.

 

이와 같이 λžŒλ‹€μ‹κ³Ό 슀트림 APIλŠ” μžλ°”μ—μ„œ μ½”λ“œμ˜ κ°„κ²°μ„±, 가독성, 그리고 νš¨μœ¨μ„±μ„ λ†’μ΄λŠ” 데 맀우 μœ μš©ν•œ 도ꡬ듀이닀. 이λ₯Ό 톡해 λ³΅μž‘ν•œ μž‘μ—…λ„ κ°„λ‹¨ν•˜κ²Œ ν‘œν˜„ν•  수 있으며, 특히 μ»¬λ ‰μ…˜ 데이터λ₯Ό λ‹€λ£° λ•Œ κ·Έ μ§„κ°€λ₯Ό λ°œνœ˜ν•œλ‹€. μžλ°”λ₯Ό 더 잘 ν™œμš©ν•˜κΈ° μœ„ν•΄ κΌ­ μ΅ν˜€λ‘λ©΄ μ’‹λ‹€!