안녕하세요? 사진찍는 개발자입니다.
궁금했던 Java8 의 Stream 에 대해 정리한 내용 포스팅합니다.

Java 8에 추가된 스트림(Stream) API는 데이터를 더 선언적, 간결하고 가독성 있는 방식으로 처리할 수 있게 도와줍니다.
이는 대량의 데이터를 효율적으로 처리하는 데 유용하며, 병렬처리도 지원하여 성능 향상을 도모할 수 있습니다.
스트림 API 사용의 주요 이점은 다음과 같습니다:
- 읽기 쉬운 코드: 스트림은 함수형 프로그래밍 패러다임을 따르므로, 코드가 더욱 읽기 쉽고 이해하기 쉬워집니다.
- 효율적인 데이터 처리: 스트림은 '게으른 연산'을 지원합니다. 즉, 필요한 시점에서만 연산이 수행되므로 메모리 사용량과 계산 비용을 절약할 수 있습니다.
- 병렬처리 가능: 스트림은 병렬처리를 지원하여 멀티코어 아키텍처에서 성능 향상을 얻을 수 있습니다.
아래에는 Java 8 이전의 방식과 스트림 API를 사용한 방식의 차이점을 보여주는 예제 코드를 제공하겠습니다.
Java 8 이전:
List<String> names = new ArrayList<>();
for (User user : users) {
if (user.getAge() > 18) {
names.add(user.getName());
}
}
위 코드는 모든 사용자들 중에서 나이가 18세 초과인 사람들의 이름만 리스트에 추가하는 작업입니다.
java 8 Stream API 사용:
List<String> names = users.stream()
.filter(user -> user.getAge() > 18)
.map(User::getName)
.collect(Collectors.toList());
위 코드도 동일한 작업을 수행하지만, filter, map, collect와 같은 함수형 메서드를 활용하여 간결하고 가독성 있는 형태로 작성되었습니다.
이 예제에서 볼 수 있듯이, 스트림 API는 각 요소에 대해 순차적으로 연산(filtering, mapping 등)을 적용하며 결과 컬렉션(list of names)을 생성합니다. 이러한 방식은 읽기 쉽고 유지보수하기 편리하며, 병렬 처리를 쉽게 적용할 수 있다는 장점이 있습니다.
여기서 기존 자료들은 자기들만 아는 걸 클래스 몇줄 적어주고 끝내서 오히려 초보들은 그런가 하는 부분들이 너무 신경써여서 다시 확인해 봤다습니다.
각 기본 function 들에 대한 내용을 정리입니다.
Java 8의 Stream API는 데이터 처리를 위한 다양한 메서드를 제공합니다. 여기서는 filter(), map(), 그리고 collect()에 대해 설명하겠습니다.
- filter(Predicate predicate): 스트림에서 특정 조건을 만족하는 요소만 선택하여 새로운 스트림을 생성합니다. 이때 사용되는
Predicate인터페이스는 매개변수를 받아 boolean 값을 반환하는 함수형 인터페이스입니다. - map(Function mapper): 각 요소를 특정 함수를 통해 변환하여 새로운 스트림을 생성합니다. 이때 사용되는
Function인터페이스는 한 개의 매개변수를 받아 결과값을 반환하는 함수형 인터페이스입니다. - collect(Collector collector): 스트림의 모든 요소를 수집하여 컬렉션 또는 다른 형태의 값으로 변환합니다. 이때 사용되는
Collector인터페이스는 스트림 요소들의 누적(accumulation) 방법을 정의합니다.
이러한 메서드들은 연속된 연산 파이프라인을 구성하여 복잡한 데이터 처리 작업도 간결하게 표현할 수 있게 도와줍니다.
그리고 Stream API에서 병렬처리(parallel processing)은 매우 간단하게 적용할 수 있습니다.
기본적으로 stream() 메서드 대신 parallelStream() 메서드를 호출하면 됩니다:
List<String> names = users.parallelStream()
.filter(user -> user.getAge() > 18)
.map(User::getName)
.collect(Collectors.toList());
위 코드에서 parallelStream()은 멀티코어 프로세서 환경에서 병렬로 작업을 수행할 수 있도록 도와줍니다.
하지만 주의해야 할 점은, 모든 상황에서 병렬처리가 무조건적으로 성능 향상을 가져오지 않습니다. 데이터 크기가 작거나, 작업이 CPU보다 I/O에 의존적인 경우에는 오히려 성능이 저하될 수 있습니다. 따라서 병렬처리 적용 전 후 성능 비교 및 분석이 필요합니다.
최종적으로 기존 개발자분들도 지금껏 이야기한 내용을 편하게 확인할 수 있게 전체코드를 작성했습니다.아래 코드 보시면 기본적인 사용법 확인 가능할 겁니다.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<User> users = Arrays.asList(
new User("John", 17),
new User("Jane", 20),
new User("Tom", 22),
new User("Alice", 15)
);
List<String> names = users.stream()
.filter(user -> user.getAge() > 18)
.map(User::getName)
.collect(Collectors.toList());
System.out.println(names);
}
}
class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
위의 코드에서 main 메소드는 여러 User 객체를 포함하는 리스트를 생성하고, 이 리스트에서 나이가 18세 초과인 사용자들의 이름만을 선택하여 새로운 리스트(names)를 만듭니다. 그리고 이 names 리스트를 출력합니다.
이렇게 스트림 API와 람다 표현식을 활용하면 데이터 처리 로직을 간결하고 선언적으로 표현할 수 있습니다.
'개발 이야기 > Android (안드로이드)' 카테고리의 다른 글
| Android App 개발에 많이 사용하는 디자인패턴 (0) | 2024.06.04 |
|---|---|
| Android | Java | 특정 소수점까지 잘라서 계산 후 반올림 하기 (0) | 2024.01.31 |
| Android | 앱 화면 구성 중에 DB에서 Data 읽어올때 코딩 가이드 (0) | 2023.12.28 |
| Android | 스마트폰 설치한 앱의 APK 추출방법 (0) | 2023.12.13 |
| Android | BLE / BEACON 지원여부 체크 (0) | 2023.09.06 |
| JAVA ByteBuffer 궁금점 정리 (0) | 2023.09.04 |
| [Android] Leak Canary를 이용하여 메모리 누수개선방안 (0) | 2023.08.23 |
| Android | Camera 로 부터 들어온 영상편집 (0) | 2023.07.10 |