본문 바로가기
JAVA

[JAVA] - Stream API 이해 5

by nam_ji 2024. 5. 30.

Stream API

개념

  • 스트림은 IntStream, DoubleStream, LongStream 세 가지가 존재합니다.
  • 다만 일반 스트림에 비해 특별하게 추가된 기능은 없고 박싱 / 언박싱 관련 효율성의 장점을 갖습니다.
  • 예제
    더보기
    package lambdaExample;
    
    import java.util.*;
    
    public class LambdaBasic3 {
      public static void main(String[] args) {
        System.out.println("\n------------------Stream 기본 자료형------------------");
        BasicDataStream basicDataStream = new BasicDataStream();
        basicDataStream.basicDataStream();
      }
    }
    
    class BasicDataStream {
      public void basicDataStream () {
        ListEx listEx = new ListEx();
    
        int sum = listEx.cities.stream()
            .mapToInt(CityEx::getPopulation) // IntStream으로 변환
            .sum();
    
        System.out.println(sum);
      }
    }
    
    class CityEx {
      private String name;
      private double area;     // 면적
      private int population;  // 인구
      private String areaCode; // 지역 번호
    
      // 필드 전체를 파라미터로 받는 생성자
      public CityEx (String name, double area, int population, String areaCode) {
        this.name = name;
        this.area = area;
        this.population = population;
        this.areaCode = areaCode;
      }
    
      // getter
      public String getName () {
        return name;
      }
      public double getArea () {
        return area;
      }
      public int getPopulation() {
        return population;
      }
      public String getAreaCode () {
        return areaCode;
      }
    }
    
    class ListEx {
      List<CityEx> cities = new ArrayList<>(
          Arrays.asList(
              new CityEx("Seoul", 605.2, 9720846, "02"),
              new CityEx("Incheon", 1063.3, 2947217, "032"),
              new CityEx("Ulsan", 1062, 1142190, "052"),
              new CityEx("Daegu", 883.5, 2427954, "053"),
              new CityEx("Gwangju", 501.1, 1455048, "062"),
              new CityEx("Busan", 770.1, 3404423, "051"))
      );
    }
    
    /*
    출력
    ------------------Stream 기본 자료형------------------
    21097678
    */

변환 방법

  • Stream 클래스에 포함된 세 가지 메서드를 사용합니다.
  • Stream::mapToInt -> IntStream 반환
  • Stream::mapToDouble -> DoubleStream 반환
  • Stream::mapToLong -> LongStream 반환
  • 기본형 타입 스트림으로 바꾸었으니 반대로 일반형인 Stream<T>으로도 다시 변환할 수 있습니다.
  • IntStream::boxed
  • DoubleStream::boxed
  • LongStream::boxed
  • 메서드 명은 모두 boxed로 같습니다.

Optional 활용

    • 최대값 등 nullable 가능성이 있는 최종 연산은 Optional<T>를 반환합니다.
    • Optional<Integer> max = listEx.cities.stream()
              .max(CityEx::getPopulation)
              .stream().reduce(Integer::max);


    • Optional<T>는 레퍼런스 타입에서만 활용할 수 있습니다.
    • 그러나 기본형 타입은 null이 따로 존재하지 않습니다.
    • int형 계산을 끝마친 결과가 0이라고 가정합니다.
    • int의 기본값은 0인데, 결과도 0이라는 것이 계산을 안 했다는 말은 아닙니다.
    • 이런 애매한 상황을 위해 기본형 타입에서도 사용할 수 있는 Optional 클래스가 존재합니다.
    • OptionalInt
    • OptionalDouble
    • OptionalLong
    • 사용 예시
      더보기
      package lambdaExample;
      
      import java.util.*;
      
      public class LambdaBasic3 {
        public static void main(String[] args) {
          System.out.println("\n------------------Stream 기본 자료형2------------------");
          BasicDataStream2 basicDataStream2 = new BasicDataStream2();
          basicDataStream2.basicDataStream2();
        }
      }
      
      class BasicDataStream2 {
        public void basicDataStream2 () {
          ListEx listEx = new ListEx();
      
          OptionalInt max = listEx.cities.stream()
              .mapToInt(CityEx::getPopulation)
              .max();
      
          System.out.println(max);
        }
      }
      
      class CityEx {
        private String name;
        private double area;     // 면적
        private int population;  // 인구
        private String areaCode; // 지역 번호
      
        // 필드 전체를 파라미터로 받는 생성자
        public CityEx (String name, double area, int population, String areaCode) {
          this.name = name;
          this.area = area;
          this.population = population;
          this.areaCode = areaCode;
        }
      
        // getter
        public String getName () {
          return name;
        }
        public double getArea () {
          return area;
        }
        public int getPopulation() {
          return population;
        }
        public String getAreaCode () {
          return areaCode;
        }
      }
      
      class ListEx {
        List<CityEx> cities = new ArrayList<>(
            Arrays.asList(
                new CityEx("Seoul", 605.2, 9720846, "02"),
                new CityEx("Incheon", 1063.3, 2947217, "032"),
                new CityEx("Ulsan", 1062, 1142190, "052"),
                new CityEx("Daegu", 883.5, 2427954, "053"),
                new CityEx("Gwangju", 501.1, 1455048, "062"),
                new CityEx("Busan", 770.1, 3404423, "051"))
        );
      }
      
      /*
      출력
      ------------------Stream 기본 자료형2------------------
      OptionalInt[9720846]
      */
  • 기본형 Optional도 Optional<T>와 마찬가지로 .isPresent(), .orElse() 등의 메서드를 갖습니다.

최종 코드

더보기
package lambdaExample;

import java.util.*;

public class LambdaBasic3 {
  public static void main(String[] args) {
    System.out.println("\n------------------Stream 기본 자료형------------------");
    BasicDataStream basicDataStream = new BasicDataStream();
    basicDataStream.basicDataStream();

    System.out.println("\n------------------Stream 기본 자료형2------------------");
    BasicDataStream2 basicDataStream2 = new BasicDataStream2();
    basicDataStream2.basicDataStream2();
  }
}

class BasicDataStream2 {
  public void basicDataStream2 () {
    ListEx listEx = new ListEx();

//    Optional<Integer> max = listEx.cities.stream()
//        .max(CityEx::getPopulation)
//        .stream().reduce(Integer::max);

    OptionalInt max = listEx.cities.stream()
        .mapToInt(CityEx::getPopulation)
        .max();

    System.out.println(max);
  }
}

class BasicDataStream {
  public void basicDataStream () {
    ListEx listEx = new ListEx();

    int sum = listEx.cities.stream()
        .mapToInt(CityEx::getPopulation) // IntStream으로 변환
        .sum();

    System.out.println(sum);
  }
}

class CityEx {
  private String name;
  private double area;     // 면적
  private int population;  // 인구
  private String areaCode; // 지역 번호

  // 필드 전체를 파라미터로 받는 생성자
  public CityEx (String name, double area, int population, String areaCode) {
    this.name = name;
    this.area = area;
    this.population = population;
    this.areaCode = areaCode;
  }

  // getter
  public String getName () {
    return name;
  }
  public double getArea () {
    return area;
  }
  public int getPopulation() {
    return population;
  }
  public String getAreaCode () {
    return areaCode;
  }
}

class ListEx {
  List<CityEx> cities = new ArrayList<>(
      Arrays.asList(
          new CityEx("Seoul", 605.2, 9720846, "02"),
          new CityEx("Incheon", 1063.3, 2947217, "032"),
          new CityEx("Ulsan", 1062, 1142190, "052"),
          new CityEx("Daegu", 883.5, 2427954, "053"),
          new CityEx("Gwangju", 501.1, 1455048, "062"),
          new CityEx("Busan", 770.1, 3404423, "051"))
  );
}

/*
출력
------------------Stream 기본 자료형------------------
21097678

------------------Stream 기본 자료형2------------------
OptionalInt[9720846]
*/

 

'JAVA' 카테고리의 다른 글

[JAVA] - indexOf, lastIndexOf 특정 문자 위치 찾기  (0) 2024.05.31
[JAVA] - Stream API 이해 6  (0) 2024.05.31
[JAVA] - Stream API 이해 4  (0) 2024.05.29
[JAVA] - Stream API 이해 3  (0) 2024.05.28
[JAVA] - Stream API 이해 2  (0) 2024.05.27