[Java] Stream API

sliver gun·2025년 4월 5일
2

공부

목록 보기
3/3
post-thumbnail

Stream API란?

배열 혹은 컬렉션 인스턴스들을 다루기 위한 람다식 처리과정이다.

데이터 소스를 가공하고 손쉽게 원하는 결과를 반환해주는 인터페이스이다.

Stream API의 특징

  1. 원본 데이터를 변경하지 않는다

    Stream API는 원본에서 따로 Stream 객체를 생성하기 때문에 따로 작업하더라도 원본 데이터는 변경되지 않는다.

  2. 재사용이 안된다.

    이미 사용되고 닫힌 Stream은 다시 사용할 수 없다.

  3. 작업을 내부적으로 반복해서 처리한다.

    Stream API의 반복 코드는 메소드 내부에 숨어져 있어 깔끔한 코드 작성이 가능하다.

Stream API의 사용 과정

Stream 객체를 통해 결과값을 얻으려면 다음과 같은 과정을 지켜야 한다.

  1. Stream을 생성한다.
  2. 생성된 Stream 객체를 Stream 전용 메소드로 중간가공한다.
  3. 중간 가공된 객체를 최종 연산을 통해 결과값을 도출한다.

예를 들어서

정수형 배열에서 짝수만 남겨두고 총합을 구하기

를 한다면?

int[] numbers = {1, 2, 3, 4, 5, 6};

int sum = IntStream.of(numbers)          // 정수형 배열을 Stream으로 생성하고
                .filter(n -> n % 2 == 0) // 짝수만 남겨두고
                .sum();                  // 총합을 구한다.

사용 과정

생성

Collection.stream() : 요소를 기준으로 생성

List<String> list = Arrays.asList("사원1", "사원2", "사원3", "사원4");
Stream<String> streamFromList = list.stream();

Stream.of() : 값을 기준으로 스트림 생성

String[] array = {"관리자1", "관리자2", "관리자3", "관리자4"};
Stream<String> streamFromArray = Stream.of(array);

Arrays.stream(T[] array) : 배열 기준으로 스트림 생성

String[] array = {"관리자1", "관리자2", "관리자3", "관리자4"};
Stream<String> streamFromArray2 = Arrays.stream(array);

Stream을 생성하면 Stream 자료형으로 반환된다.

조건 연산

🎈 filter(), distinct()

filter : 조건에 맞는 요소만 통과한다.

distinct : 중복을 제거한다.

List<Integer> list = List.of(1, 2, 3, 4, 5);
list.stream()
		.filter(n -> n % 2 == 0) // 짝수만
// 2, 4

List<Integer> list2 = List.of(1, 2, 2, 3, 3, 3);
list2.stream()
		 .distinct()
// 1, 2, 3

🎈 map(). flatMap()

map : 각 요소를 변환한다.

flatMap : 요소를 펼쳐서 하나의 스트림으로 변환한다.

List<String> list = List.of("a", "bb", "ccc");
list.stream()
    .map(String::length)
// 1, 2, 3

List<String> list = List.of("Hello", "World");
list.stream()
    .flatMap(str -> Arrays.stream(str.split("")))
// H, e, l, l, o, W, o, r, l, d

🎈 limit()

앞에서부터 n개까지 선택한다.

IntStream.rangeClosed(1, 10)
	       .limit(3)
// 1, 2, 3

🎈 sorted()

요소를 정렬한다.

List<String> list = List.of("b", "a", "c");
list.stream()
    .sorted()
// a, b, c

최종 연산

🎈 forEach()

모든 요소에 대해 지정한 메소드 동작 수행한다.

List<String> names = List.of("a", "b", "c");

names.stream()
     .forEach(System.out::println);
// a, b, c

🎈 findFirst()

첫 번째 요소를 반환한다.

List<String> list = List.of("a", "b", "c");

list.stream()
		.findFirst();
		.ifPresent(System.out::println);
// a

여기서 ifPresent는 findFirst의 반환값이 존재할 때만 출력시키도록하는 보조함수이다.

🎈 anyMatch(), allMatch()

anyMatch : 조건 검사 (하나라도 만족하면 true)

allMatch : 조건 검사 (전부 만족해야 true)

List<Integer> list = List.of(1, 2, 3, 4);

boolean hasEven = list.stream().anyMatch(n -> n % 2 == 0);
boolean allPositive = list.stream().allMatch(n -> n > 0);
// hasEven : true
// allPositive : true

🎈 count(), min(), max()

count : 요소 수를 반환한다.

min : 최소값을 반환한다.

max : 최대값을 반환한다.

List<Integer> list = List.of(5, 1, 3, 9);

long count = list.stream().count();
int min = list.stream().min(Integer::compare).get();
int max = list.stream().max(Integer::compare).get();
// count : 4
// min : 1
// max : 9

🎈 sum(), average()

sum : 합계를 반환한다. (숫자형 전용)

average : 평균을 반환한다. (숫자형 전용)

int[] arr = {10, 20, 30};

int total = Arrays.stream(arr).sum();
OptionalDouble avg = Arrays.stream(arr).average();
// total = 60
// avg = 20.0

🎈 collect()

결과를 List나 문자열 등으로 결과를 수집한다.

List<String> names = List.of("Kim", "Lee", "Park");

String result = names.stream()
                     .collect(Collectors.joining(", "));
// result : Kim, Lee, Park

List<String> filtered = names.stream()
                             .filter(n -> n.startsWith("P"))
                             .collect(Collectors.toList());
// filtered : [Park]

결론

멋사에서 Java Stream API를 배우면서 여러모로 이해가 되지 않는 부분들이 있어서 기본 개념과 주요 메서드들에 대해서 조사해보았다. 중간에 함수 인터페이스에 대한 설명이 빠져있어 그 부분에 대해선 추가적인 정리가 필요할 것 같다.

0개의 댓글