Java Stream 심화 정리 (메서드 참조, IntStream, mapToInt, collect)

scminy0527·2026년 3월 3일
post-thumbnail

자바 공부 중 스트림을 배우면서
람다식, :: 메서드 참조, IntStream, collect()
처음 보는 기능들이 많이 나왔다.

이번 글에서는 내가 헷갈렸던 부분들을 중심으로 정리해보려고 한다.


1. :: 메서드 참조란 무엇인가?

스트림에서 자주 보이는 문법:

users.stream()
     .map(User::getName)
     .forEach(System.out::println);

이게 처음에는 굉장히 신기했다.


메서드 참조의 정체

::람다식을 더 간결하게 표현한 문법이다.

예를 들어:

user -> user.getName()

User::getName

로 줄일 수 있다.


내부적으로 무슨 일이 벌어질까?

.map(User::getName)

은 사실 이렇게 해석된다:

.map(user -> user.getName())

스트림이 Function<User, String> 형태를 요구하고,
getName() 이 그 시그니처와 일치하기 때문에 연결되는 것이다.


System.out::println 의 의미

.forEach(System.out::println);

이건

.forEach(name -> System.out.println(name));

과 동일하다.

System.outPrintStream 객체이고,
그 객체의 println() 메서드를 Consumer<T> 형태로 전달한 것이다.


핵심 정리

메서드 참조는

함수형 인터페이스의 추상 메서드 시그니처와
일치하는 메서드를 자동 연결하는 문법

이다.


IntStream 이란 무엇인가?

스트림에는 두 종류가 있다.

객체 스트림

Stream<T>

예:

- Stream<String>
- Stream<User>
- Stream<Integer>

기본형 전용 스트림

  • IntStream
  • LongStream
  • DoubleStream

이건 primitive 전용이다.


IntStream.range()

IntStream.range(0, 10)

→ 0 ~ 9 까지 숫자 스트림 생성

IntStream.rangeClosed(1, 10)

→ 1 ~ 10 포함


최대 / 최소 / 합계

IntStream.range(0, 10).max();
IntStream.range(0, 10).min();
IntStream.range(0, 10).sum();

여기서 중요한 점은:

sum(), max(), min()IntStream 전용 기능이다.


3. mapToInt 를 왜 사용할까?

예제:

int totalAge = users.stream()
    .mapToInt(user -> user.getAge())
    .sum();

만약 map만 사용하면?

users.stream()
     .map(user -> user.getAge());

이건

Stream<Integer>

가 된다.

하지만 Stream<Integer> 에는 .sum() 이 없다


그래서 mapToInt 사용

.mapToInt(user -> user.getAge())

이건

Stream<User>IntStream

으로 변환하는 과정이다.

그 다음 .sum() 이 가능해진다.


핵심 이유

  • 기본형 전용 연산(sum, max 등)을 쓰기 위해
  • 객체 생성(Integer) 비용을 줄이기 위해
  • 성능 최적화를 위해

4. collect() 와 Collectors.joining()

String result = datas1.stream()
    .map(String::valueOf)
    .collect(Collectors.joining(", "));

이건

1, 2, 3, 4

형태로 문자열을 합쳐준다.


collect() 란?

스트림의 최종 연산이다.

스트림 결과를 원하는 자료형으로 모아주는 역할

예:

  • Collectors.toList()
  • Collectors.joining()
  • Collectors.groupingBy()

5. mapToObj 란 무엇인가?

예제:

data.chars()
    .map(c -> c + 32)
    .mapToObj(c -> (char)c)

chars() 는 무엇인가?

StringIntStream

문자는 내부적으로 숫자(Unicode 코드값) 이기 때문이다.


mapToObj 의 역할

IntStreamStream<T>

즉, 기본형 스트림을 객체 스트림으로 변환하는 메서드이다.


왜 필요할까?

IntStream 의 map()

intint

만 가능하다.

객체로 변환하려면 반드시 mapToObj() 를 사용해야 한다.


6. 전체 흐름 정리

Stream<User>
   ↓ mapToInt
IntStream
   ↓ sum
int 결과

String
   ↓ chars()
IntStream
   ↓ map()
IntStream
   ↓ mapToObj()
Stream<Character>
   ↓ collect()
String

최종 정리

:: 는 람다식을 줄인 메서드 참조
✔ IntStream 은 primitive 전용 스트림
✔ sum(), max() 는 IntStream 전용
✔ mapToInt 는 객체 스트림 → 기본형 스트림 변환
✔ mapToObj 는 기본형 스트림 → 객체 스트림 변환
✔ collect 는 스트림을 최종 결과로 모으는 연산


스트림은 단순히 "반복문 줄이기" 가 아니라,

데이터를 흐름처럼 단계별로 변환하는 구조

라는 걸 이번에 확실히 이해하게 되었다.

스트림은 반복문을 감추는 기술이 아니라,
데이터의 흐름을 함수처럼 다루는 구조다.

profile
비전공자에서 시작해 Flutter로 실서비스를 만들었고, 더 깊은 개발을 향해 계속 성장 중인 개발자

0개의 댓글