Java Stream API 사용법
Stream API는 Java 8에서 도입된 매우 유용한 기능으로, 데이터를 효율적이고 간결하게 처리할 수 있는 방법을 제공합니다. 이 글에서는 Stream API의 기본 개념부터 다양한 활용 방법까지 살펴보며, 실용적인 예시와 함께 Stream API가 왜 중요한지 알아보겠습니다.
Stream API란 무엇인가?
Stream은 데이터를 처리하기 위한 흐름을 나타냅니다. Java의 Stream API는 컬렉션(Collection), 배열(Array) 또는 I/O 자원을 일관된 방식으로 처리하는 기능을 제공합니다. 이로 인해 반복적인 데이터 처리가 단순화되고, 코드의 가독성이 향상됩니다.
Stream API의 주요 특징은 다음과 같습니다:
• 함수형 프로그래밍 스타일: 람다 표현식을 사용하여 데이터를 처리합니다.
• 지연 연산(Lazy Evaluation): 데이터를 미리 처리하지 않고, 실제 필요한 순간에 연산이 이루어집니다.
• 병렬 처리 지원: 대용량 데이터를 병렬로 처리하여 성능을 개선할 수 있습니다.
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
names.stream()
.filter(name -> name.startsWith("A"))
.forEach(System.out::println); // 결과: Alice
위 예시에서 stream() 메서드를 통해 데이터를 흐름으로 변환하고, filter()로 ‘A’로 시작하는 이름만 선택하여 출력하고 있습니다. 이처럼 Stream은 데이터를 한 단계씩 변환하고 처리하는 방식으로 동작합니다.
Stream의 기본 연산
Stream은 크게 두 가지 종류의 연산으로 나뉩니다: 중간 연산과 최종 연산입니다.
• 중간 연산: 데이터를 변환하거나 필터링하는 작업을 하고, 새로운 Stream을 반환합니다. 이때 연산은 실제로 실행되지 않으며, 최종 연산이 호출될 때 지연 평가(Lazy Evaluation)됩니다.
• 예: filter(), map(), sorted()
• 최종 연산: Stream을 끝내고 결과를 반환하는 연산입니다. 최종 연산이 호출되면 모든 중간 연산이 실제로 수행됩니다.
• 예: forEach(), collect(), reduce()
List<String> fruits = Arrays.asList("apple", "banana", "cherry");
long count = fruits.stream()
.filter(fruit -> fruit.contains("a"))
.count(); // 결과: 3
여기서 filter()는 중간 연산, count()는 최종 연산입니다. count()가 호출되기 전까지 실제로 데이터를 처리하지 않습니다.
자주 사용하는 Stream 메서드
Stream API에서 가장 자주 사용되는 몇 가지 메서드를 소개합니다.
• filter(): 조건에 맞는 요소만 필터링합니다.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println); // 결과: 2, 4
• map(): 각 요소를 변환합니다.
List<String> words = Arrays.asList("apple", "banana", "cherry");
words.stream()
.map(String::toUpperCase)
.forEach(System.out::println); // 결과: APPLE, BANANA, CHERRY
• sorted(): 스트림의 요소를 정렬합니다.
List<Integer> nums = Arrays.asList(3, 1, 4, 1, 5, 9);
nums.stream()
.sorted()
.forEach(System.out::println); // 결과: 1, 1, 3, 4, 5, 9
• collect(): 스트림의 결과를 다시 컬렉션으로 변환합니다.
List<String> upperCaseFruits = fruits.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
병렬 처리
Stream API는 간단하게 병렬 처리를 지원합니다. parallelStream()을 사용하면 쉽게 병렬 처리가 가능해집니다. 이는 대용량 데이터를 처리할 때 성능을 크게 향상시킬 수 있습니다.
List<Integer> largeList = new ArrayList<>(Collections.nCopies(1000000, 1));
largeList.parallelStream()
.map(n -> n * 2)
.forEach(System.out::println);
병렬 처리에서는 데이터 순서가 보장되지 않으므로, 순서가 중요한 경우에는 주의가 필요합니다.
데이터 축소하기
reduce()는 Stream의 모든 요소를 하나의 값으로 결합하는 연산을 제공합니다. 이는 합계, 최대값, 최소값 등을 계산할 때 유용합니다.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.reduce(0, Integer::sum); // 결과: 15
이 코드에서 reduce()는 스트림의 모든 숫자를 더해 하나의 값을 반환합니다.
마무리
Stream API는 데이터를 처리하는 강력한 도구로, 코드의 가독성을 높이고, 복잡한 작업을 간결하게 처리할 수 있습니다. 기본적인 필터링, 변환, 정렬뿐만 아니라, 병렬 처리와 데이터 축소 등의 기능도 쉽게 사용할 수 있습니다. Stream API를 잘 활용하면 코드의 효율성을 크게 높일 수 있습니다.
'JAVA' 카테고리의 다른 글
Java 접근 제어자 종류와 이해 (0) | 2024.10.22 |
---|---|
Java Enum 사용법과 활용 예시 (10) | 2024.10.18 |
Java에서의 CORS 설정하기 (0) | 2024.10.18 |