[java] ArrayList를 int[] 배열로 변환하는 가장 깔끔한 방법

CHOI HONGSEO·2026년 4월 4일

알고리즘 문제를 풀다 보면 결과값의 크기를 미리 알 수 없어 동적 배열인 ArrayList에 데이터를 담아두는 경우가 많습니다. 하지만 문제의 반환 타입(Return Type)이 기본형 배열인 int[]로 고정되어 있다면 타입 불일치 문제가 발생합니다.

public static int[] solution(int[] num_list, int n) {
    ArrayList<Integer> list = new ArrayList<>();
    
    for(int i = 0; i < num_list.length; i += n) {
        list.add(num_list[i]);
    }
    
    // 컴파일 에러: ArrayList<Integer>를 int[]로 바로 반환할 수 없음
    return list; 
}

ArrayListtoArray() 메서드를 사용하더라도 Integer[]Object[]로만 변환될 뿐, 원시 타입(Primitive Type)인 int[]로는 바로 변환되지 않습니다.

이때 자바 8부터 도입된 Stream API를 사용하면 이 형변환 과정을 단 한 줄의 코드로 우아하게 처리할 수 있습니다.

`return list.stream().mapToInt(i -> i).toArray();`

이 코드가 내부적으로 어떻게 동작하여 ArrayList<Integer>int[]로 변환하는지 3단계로 나누어 살펴보겠습니다.

Stream API 변환 파이프라인 분석

1. .stream() : 객체 스트림 생성

가장 먼저 컬렉션(ArrayList)을 스트림으로 변환합니다.

  • list.stream()을 호출하면 ArrayList에 담긴 데이터들을 순차적으로 처리할 수 있는 Stream<Integer> 타입의 객체 스트림이 생성됩니다.
  • 이 단계에서는 여전히 데이터가 래퍼 클래스(Wrapper Class)인 Integer 객체 형태로 존재합니다.

2. .mapToInt(i -> i) : IntStream 변환 및 오토 언박싱 (Auto-Unboxing)

스트림의 요소를 기본형 스트림으로 변환하는 핵심 단계입니다.

  • mapToInt() 메서드는 기존의 Stream<Integer>를 원시 타입 스트림인 IntStream으로 매핑(Mapping)합니다.
  • 매개변수로 전달된 람다식 i -> i는 들어온 Integer 객체를 그대로 반환하라는 의미입니다.
  • 이때, 자바 컴파일러는 내부적으로 Integer 객체에서 기본형 int 값을 추출하는 오토 언박싱(Auto-Unboxing)을 수행합니다.
  • (참고: 람다식 대신 메서드 참조인 Integer::intValue를 사용하면 언박싱 과정을 더 명시적으로 표현할 수 있습니다.)

3. .toArray() : 배열로 수집 (종단 연산)

변환된 스트림 데이터를 최종적으로 배열로 묶어냅니다.

  • 스트림 파이프라인의 최종 연산(Terminal Operation)입니다.
  • 언박싱되어 IntStream을 통과한 순수 int 값들을 모아, 새로운 int[] 배열을 메모리에 할당하고 값을 복사한 뒤 이를 반환합니다.

요약

list.stream().mapToInt(i -> i).toArray()는 단순한 마법이 아니라, 스트림 생성 ➔ 객체의 언박싱 매핑 ➔ 원시 타입 배열로의 수집이라는 명확한 자바의 동작 방식을 따르고 있습니다.

반복문을 직접 작성하여 배열로 옮겨 담는 것(for문 사용)보다 성능 오버헤드는 아주 미세하게 존재할 수 있으나, 가독성과 유지보수성이 압도적으로 뛰어나기 때문에 실무와 코딩 테스트에서 가장 널리 권장되는 방식입니다.

profile
곧 성공할 개발자입니다.

0개의 댓글