자바(Java)로 알고리즘 문제를 풀거나 스트림(Stream) API를 다루다 보면, 컬렉션(List 등)을 원시 타입 배열(int[])로 변환할 때 .mapToInt(i -> i)라는 코드를 매우 자주 사용하게 됩니다.
List<Integer> list = List.of(1, 2, 3);
int[] arr = list.stream().mapToInt(i -> i).toArray();
처음 이 문법을 접하면 "이게 정확히 무슨 뜻이지?", "i는 Integer에서 int로 바뀌는 건가?", "i 대신 다른 변수나 식을 써도 되나?" 와 같은 의문이 들 수 있습니다. 오늘은 자바 8부터 도입된 람다식(Lambda Expression)을 바탕으로 이 코드의 정확한 동작 원리와 활용법을 정리해 보겠습니다.
i -> i 의 정확한 의미와 오토 언박싱 (Auto-Unboxing)i -> i는 자바의 람다식 문법으로, 입력값(Input) -> 반환값(Output)의 구조를 띱니다.
List<Integer>와 같은 컬렉션에서 생성된 스트림(Stream<Integer>)을 통과하는 데이터들은 기본형 int가 아닌 래퍼 클래스(Wrapper Class)인 Integer 객체입니다. .mapToInt() 메서드는 이 객체 스트림을 원시 타입 스트림인 IntStream으로 변환(매핑)하는 역할을 합니다.
i (입력값): 스트림에서 전달되는 Integer 타입의 객체입니다.i (반환값): 매핑의 결과로 반환할 값입니다. .mapToInt()를 사용했기 때문에 자바 컴파일러는 최종 반환 타입이 기본형 int여야 함을 알고 있습니다.따라서 자바 컴파일러는 들어온 Integer 객체를 그대로 반환할 때, 내부적으로 객체에서 원시 타입 값을 추출하는 오토 언박싱(Auto-Unboxing)을 수행하여 int 값으로 변환해 내보냅니다.
람다식에서 사용된 i는 특수한 키워드가 아니라 단순한 매개변수(Parameter) 이름일 뿐입니다. for (int i = 0; i < 10; i++)에서 사용하는 i와 동일한 역할입니다.
따라서 코드의 가독성을 높이기 위해 개발자가 원하는 이름으로 자유롭게 변경하여 사용할 수 있으며, 모두 완벽하게 동일하게 동작합니다.
// 아래 코드는 모두 100% 동일하게 작동합니다.
.mapToInt(i -> i)
.mapToInt(num -> num)
.mapToInt(x -> x)
.mapToInt(value -> value)
mapToInt의 실무 및 응용 활용법단순히 들어온 값을 그대로 통과시키는 것 외에도, 람다식을 조작하여 스트림 요소의 값을 입맛대로 가공하거나 추출할 수 있습니다.
스트림을 통과하는 데이터에 즉각적으로 수학적 연산을 적용하여 매핑할 수 있습니다. 예를 들어 모든 요소의 값을 2배로 만들고 싶다면 아래와 같이 작성합니다.
// 들어온 x를 2배(x * 2)로 연산하여 IntStream으로 반환
int[] arr = list.stream().mapToInt(x -> x * 2).toArray();
i -> i를 통한 오토 언박싱에 의존하는 대신, Integer 클래스가 가진 intValue() 메서드를 직접 호출하라고 명시할 수 있습니다. 이 방식은 자바의 메서드 참조(Method Reference) 문법으로, 실무에서 더 명확하고 정석적인 코딩 스타일로 권장됩니다.
// i -> i 와 동일하게 동작하며, 더 명시적인 표현 방식입니다.
int[] arr = list.stream().mapToInt(Integer::intValue).toArray();
int 값 추출하기스트림의 원본 데이터가 Integer가 아닌 전혀 다른 객체(String 등)일 때도 유용하게 사용됩니다. 객체 내부의 특정 값을 추출하거나 변환하여 IntStream을 생성할 수 있습니다.
예시 A: 문자열 리스트를 정수 배열로 변환
List<String> strList = List.of("10", "20", "30");
// 문자열 객체(str)를 받아 파싱(Integer.parseInt) 후 int로 반환
int[] parsedArr = strList.stream().mapToInt(str -> Integer.parseInt(str)).toArray();
// 결과: [10, 20, 30]
예시 B: 문자열 객체에서 '길이' 데이터만 추출
List<String> words = List.of("apple", "banana", "kiwi");
// 문자열 객체(word)를 받아 길이(length)를 int로 반환
int[] lengths = words.stream().mapToInt(word -> word.length()).toArray();
// 결과: [5, 6, 4]