Stream & 람다식
이번 시간에는 자바 8부터 도입된 람다 표현식과 Stream API, Optional 클래스를 배웁니다. 간결하고 함수형 스타일의 프로그래밍으로 코드 생산성을 향상해 보세요!
📌 목차
- 람다 표현식 & 함수형 인터페이스
- Stream API (map, filter, collect)
- Optional 클래스
🔹 1. 람다 표현식 & 함수형 인터페이스
람다식은 간결하게 함수를 표현할 수 있는 자바 8의 문법으로, 익명 클래스를 대체하며 코드의 가독성과 유지보수성을 높여줍니다. 특히 단 하나의 추상 메서드를 가지는 @FunctionalInterface에서 강력한 힘을 발휘합니다.
🖥️ 람다식 예제
@FunctionalInterface
interface Calculator {
int operate(int a, int b);
}
public class LambdaExample {
public static void main(String[] args) {
Calculator add = (a, b) -> a + b;
Calculator subtract = (a, b) -> a - b;
System.out.println("10 + 5 = " + add.operate(10, 5));
System.out.println("10 - 5 = " + subtract.operate(10, 5));
}
}
람다식은 지역 변수 캡처도 지원하며, (a, b) -> a + b처럼 매우 간단하게 표현할 수 있습니다. 이를 통해 코드 라인을 줄이고, 컬렉션이나 콜백 등에서 효율적으로 활용할 수 있습니다.
🔹 2. Stream API
Stream은 자바 컬렉션 처리에서 선언적 스타일을 제공하여 데이터를 필터링, 매핑, 수집 등 다양한 방식으로 처리할 수 있도록 합니다. stream() 메서드를 통해 시작하며, map(), filter(), sorted(), collect() 등의 연산자를 연결하여 사용합니다.
🖥️ Stream 예제: 문자열 리스트에서 필터링 후 대문자로 변환
import java.util.*;
import java.util.stream.*;
public class StreamExample {
public static void main(String[] args) {
List names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Alex", "Ann");
List result = names.stream()
.filter(name -> name.startsWith("A"))
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(result); // [ALICE, ALEX, ANN]
}
}
Stream의 강력한 장점 중 하나는 중간 연산과 최종 연산을 분리하여 지연 평가를 수행한다는 것입니다. 또한 parallelStream()을 사용하면 손쉽게 병렬 처리도 가능합니다.
🧠 더 많은 예제
List nums = Arrays.asList(1, 2, 3, 4, 5, 6);
int sum = nums.stream()
.filter(n -> n % 2 == 0)
.mapToInt(n -> n * 2)
.sum();
System.out.println("짝수 * 2의 합: " + sum); // 2*2 + 4*2 + 6*2 = 24
🔹 3. Optional 클래스
Optional은 Java 8에서 null 처리의 안전성을 높이기 위해 도입된 컨테이너 클래스입니다. 객체의 유무에 따라 다양한 메서드를 제공하며, NullPointerException 방지를 위한 코드를 깔끔하게 작성할 수 있습니다.
🖥️ Optional 사용 예제
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional optionalName = Optional.of("Java");
optionalName.ifPresent(name -> System.out.println("이름: " + name));
String result = optionalName.orElse("기본값");
System.out.println("결과: " + result);
Optional empty = Optional.empty();
System.out.println("비어있는 값 처리: " + empty.orElse("값이 없습니다"));
}
}
또한, map(), filter(), flatMap() 등의 메서드를 이용하여 Optional 내부의 값을 더욱 정교하게 다룰 수 있습니다. 특히 중첩 Optional 처리나 스트림과의 연계 사용 시 매우 유용합니다.
💡 고급 예제
Optional email = Optional.ofNullable(getUserEmail());
String finalEmail = email
.filter(e -> e.contains("@"))
.map(String::toLowerCase)
.orElse("이메일 형식이 아닙니다");
System.out.println("최종 이메일: " + finalEmail);
'Programming' 카테고리의 다른 글
| JAVA JVM 구조 및 튜닝 (0) | 2025.11.30 |
|---|---|
| JAVA 모던 Java 문법 (Java 8~21) (23) | 2025.11.29 |
| JAVA 리플렉션과 어노테이션 (63) | 2025.11.27 |
| JAVA 디자인 패턴 (40) | 2025.11.26 |
| JAVA 네트워크 프로그래밍 (43) | 2025.11.25 |