프로그래밍자바 개발자

자바 스트림 API란 무엇이며, 컬렉션 처리 작업에 올바르게 사용하는 방법과 데이터 스트림 작업 시 고려해야 할 주의 사항은 무엇입니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

질문 역사:

스트림 API는 자바 8에 추가되어 기능적 프로그래밍과 컬렉션의 병렬 처리를 용이하게 합니다. 이는 람다 표현식을 통해 데이터에 대한 작업 체인을 설명하는 편리한 방법을 제공합니다.

문제:

스트림 API 없이 컬렉션을 필터링, 정렬 및 집계하기 위해 번거로운 명령형 코드를 작성해야 했습니다. 오류의 가능성, 유지 관리의 복잡성, 수동으로 병렬성을 추가하려는 비효율성.

해결책:

스트림 API는 중간(intermediate) 및 최종(terminal) 작업의 파이프라인을 구축할 수 있게 해줍니다. 스트림은 지연(lazy)되어 있으며, 데이터를 순차적 또는 병렬로 처리하며, 코드는 더 간결하고 표현력이 풍부해집니다.

컬렉션 처리의 예:

List<String> names = Arrays.asList("안나", "이반", "표트르", "예바"); names.stream() .filter(s -> s.length() > 3) .map(String::toUpperCase) .sorted() .forEach(System.out::println);

주요 특징:

  • 스트림은 지연됨: 최종 작업에서만 계산이 발생함
  • 최종 작업 후 스트림은 닫힘
  • 병렬 처리로 전환 가능(parallelStream()), 하지만 컬렉션과 함수의 스레드 안전성을 고려해야 함

간접 질문.

닫힌 스트림을 재사용할 수 있습니까?

아니요, 닫힌 스트림을 재사용하려고 하면 IllegalStateException이 발생합니다. 스트림은 일회성입니다.

스트림 생성 후 원본 컬렉션의 변화가 영향 줍니까?

네, 스트림 생성 후 최종 작업 전까지 컬렉션이 변경되면 ConcurrentModificationException이 발생할 수 있습니다.

스트림 작업 내에서 외부 가변 변수를 사용할 수 있습니까?

권장되지 않으며, 병렬 스트림에서는 예기치 않은 오류를 초래할 수 있습니다. 스트림 파이프라인에서 가변 사이드 이펙트를 피하는 것이 좋습니다.

일반적인 오류 및 안티 패턴

  • 람다/스트림 내에서 가변 외부 변수 사용
  • 중간 작업에서 즉각적인 효과를 기대(최종 작업이 없으면 아무 일도 일어나지 않음)
  • 스레드 안전하지 않은 컬렉션에 .parallelStream() 적용

실제 사례

부정적 케이스

프로그래머가 스트림을 통해 외부 목록을 변경하는 메서드를 호출하는데, 이는 순차적 실행에서는 작동하지만 병렬 실행에서는 데이터 구조에 혼란을 초래합니다.

장점:

  • 코드가 간결함

단점:

  • 경쟁 조건 및 예외 가능성
  • 스레드 안전성 위반

긍정적 케이스

전체 파이프라인이 순수하게 구성됨: 작업은 사이드 이펙트가 없고, 오직 불변 컬렉션만을 사용하며, 최종 결과는 수집기를 통해 집계됩니다.

장점:

  • 안전하고, 읽기 쉽고, 효율적인 코드
  • 병렬 스트림으로의 쉬운 전환

단점:

  • 기능적 스타일에 대한 적응이 필요함