본문 바로가기
JAVA

[JAVA] - Stream API 이해 1

by nam_ji 2024. 5. 25.

Java Stream API 이해하기

Java Stream API 개요

  • 2014년 공개된 자바 8엔 함수형 프로그래밍을 지원하는 스트림이 포함되었습니다.
  • 스트림의 추가는 자바를 완전히 새로운 형태로 작성할 수 있는 새로운 장을 열었다고 봐도 무방합니다.
  • 함축적이고 짧아진 코드를 제공하기 때문입니다.

Java 8 프로그래밍 개념

1. 스트림 처리

  • 스트림은 한 번에 한 개씩 만들어지는 연속적인 데이터 항목의 모임입니다.
  • 이론적으로 프로그램은 입력 스트림에서 하나씩 읽어들이고, 출력 스트림에 하나씩 기록됩니다.
  • 한 프로그램의 출력 스트림이 다른 프로그램의 입력 스트림이 될 수도 있습니다.

2. 행위 매개변수화 (Behavior Parameterization)

  • 코드를 API로 전달합니다
  • 더 쉽게 말하면 메서드를 매개변수로 사용할 수 있다는 것입니다.

3. 병렬성과 공유 데이터

  • 보다 쉽게 처리하는 병렬성입니다.
  • 원활한 병렬 처리를 위해서는 공유 데이터를 사용하지 않는 것이 일반적입니다.
  • 동시 접근 시 의도와는 다른 결과가 나타날수 있기 때문입니다.
  • 자바에서는 공유 데이터에 대한 접근 제어를 synchronized와 같은 키워드를 활용해서 처리했으니 속도가 굉장히 느리다는 단점이 있습니다.
  • 자바 8 스트림을 활용하면 병렬 처리를 더 쉽게 할 수 있으면서도 속도를 크게 해치지 않습니다.

자바와 함수

  • 자바는 함수보다는 메서드라는 용어를 사용합니다.
  • 그러나 자바 8 스트림에서는 함수라는 용어를 사용할 수 있습니다.
  • 객체의 메서드보다 더 일반적인 형태롤 사용하고자 정의된 요소가 필요하기 때문입니다.

1. 1급 시민

  • 자바스크립트에서는 함수 자체가 값을 가지게 할 수 있습니다.
  • 이런 함수를 1급 시민이라고 합니다.
  • 자바의 클래스는 그 자체로는 값을 가지지 않기 때문에 2급 시민입니다.

2. 메서드 참조와 1급 시민

  • 지비 8에서 새롭게 추가된 특징인 메서드 참조 기능을 활용하면 메서드를 1급 시민으로 만들 수 있습니다.
  • // OLD
    File[] hiddenFiles = new File(".").listFiles(new FileFileter() {
        public boolean accept(File file) {
            return file.isHidden();
        }
    });
    
    // NEW
    File[] hiddenFiles = new File(".").listFiles(File::isHidden);
  • File의 isHidden 메서드 자체를 값으로 전달했습니다.
  • File::isHidden 대신 (File file) -> file.isHidden()을 사용하면 익명 람다 함수로 전달합니다.

스트림

  • 자바의 Collection은 다양한 구조가 구현되어 있습니다.
  • // OLD
    Map<String, SomeObject> map = new HashMap<>();
    
    for (SomeObject obj : objs) {
        if (obj.isObject()) {
            map.put(obj.getName(), obj);
        }
    }
    
    // NEW
    Map<String, SomeObject> map = 
        objs.stream()
            .filter((SomeObject obj) -> obj.isObject())
            .collect(groupingBy(SomeObject::getName));
  • 전자는 논리적인 흐름으로 파악할 수 있다면 후자는 적절한 이름으로 이러가며 처리합니다.
  • 또 다른 차이가 있다면 foreach에서는 각 요소를 반복하며 데이터를 처리하지만 스트림 API는 라이브러리 내부에서 모든 데이터를 처리합니다.
  • 이를 내부 반복이라고 합니다.
  • objs에 많은 데이터가 담겨 있다면 foreach에서 데이터를 처리하는 시간이 많이 소요될 것입니다.
  • 그러나, stream은 병렬 처리를 쉽게 구현할 수 있기 때문에 더 빠르게 처리할 수 있습니다.