본문 바로가기
TIL

[Java] Stream API의 효율적인 사용법과 주의할 점

by 긍고 2024. 9. 25.
728x90
반응형

개요


최근 프로젝트에서 다수의 데이터를 효율적으로 처리할 방법을 고민하다가 Java Stream API를 접하게 되었다. 반복문으로 데이터를 처리하던 기존의 방식에 비해 코드가 간결해지고 가독성도 높아져서 많은 도움이 되었다.

 

하지만, Stream API를 처음 사용하다 보면 실수를 할 수 있는 부분도 많고, 성능 이슈가 발생할 수 있는 점들이 있다. 그래서 이번 포스팅에서는 Java Stream API를 어떻게 효율적으로 사용할 수 있는지, 그리고 주의할 점들을 정리해 보려고 한다.

 

Java Stream API란 무엇인가?


Stream API자바 8에서 도입된 기능으로, 컬렉션 데이터(리스트, 맵 등)를 선언적 방식으로 처리할 수 있도록 돕는다. 스트림을 사용하면 루프 없이도 데이터를 필터링, 매핑, 집계하는 등의 작업을 쉽게 처리할 수 있다.

 

기존의 반복문 방식과 다르게, Stream API는 데이터 처리 과정을 메서드 체이닝 방식으로 표현할 수 있어 가독성이 크게 향상된다.

 

효율적인 Stream 사용법


1. 필터링과 매핑

Stream API의 filter()와 map()을 사용하면 데이터를 쉽게 필터링하고 변환할 수 있다.

List<String> names = Arrays.asList("John", "Jane", "Jake", "Jill");
List<String> filteredNames = names.stream()
                                  .filter(name -> name.startsWith("J"))
                                  .map(String::toUpperCase)
                                  .collect(Collectors.toList());

System.out.println(filteredNames); // [JOHN, JANE, JAKE, JILL]

 

이처럼 filter로 조건에 맞는 요소만 추출하고, map으로 변환 작업을 쉽게 처리할 수 있다.


2. 병렬 처리

Stream API의 parallelStream()을 사용하면 다수의 데이터를 병렬로 처리하여 성능을 높일 수 있다. 하지만 무조건 병렬 처리가 성능을 높이는 것은 아니므로 상황에 맞게 사용하는 것이 중요하다.

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numbers.parallelStream().forEach(System.out::println);

 

Stream 사용 시 주의할 점


1. 재사용 불가

Stream은 한 번 사용하면 재사용이 불가능하다. 스트림을 반복해서 사용 해야 한다면, 매번 새로운 스트림을 생성해야 한다.

Stream<String> stream = names.stream();
stream.forEach(System.out::println); // 정상 작동
stream.forEach(System.out::println); // 에러 발생

2. 병렬 스트림 주의

병렬 스트림을 사용할 때는 성능 향상을 기대할 수 있지만, 작은 데이터셋에 사용하거나 잘못된 상황에서 사용하면 오히려 성능이 저하될 수 있다. 특히 공유 상태에 접근하는 경우 병렬 스트림을 신중하게 사용해야 한다.


3. 종료 연산의 중요성

Stream API의 filter(), map() 같은 중간 연산은 데이터를 변환하지만, 반드시 종료 연산(예: collect(), forEach())을 사용해야 최종 결과를 얻을 수 있다.

 

Stream API 사용 예제


아래는 리스트에서 짝수만 골라낸 후, 그 값을 제곱하는 예제다.

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> result = numbers.stream()
                              .filter(num -> num % 2 == 0)
                              .map(num -> num * num)
                              .collect(Collectors.toList());

System.out.println(result); // [4, 16, 36]

 

위 코드는 필터와 맵을 사용해 간단하게 데이터를 처리하는 예시로, 선언적으로 데이터를 변환할 수 있는 Stream API의 장점을 잘 보여준다.

 

정리


Java Stream API는 대용량 데이터를 처리할 때 매우 유용하며, 코드의 가독성을 높이고 유지 보수를 쉽게 만든다. 그러나 스트림을 재사용할 수 없다는 점, 병렬 처리를 신중히 사용해야 한다는 점, 그리고 성능 이슈를 고려한 사용이 필요하다. Stream API를 올바르게 사용하면 코드의 효율성과 성능을 크게 향상할 수 있으니, 실전에서 적극 활용해 보자.

728x90

댓글