Stream 잘 사용해보기 1편 - 생성하기

midas·2022년 5월 20일
0

Stream 잘 사용해보기

스트림 Stream 생성편

생성하기

배열 스트림

컬렉션 스트림

비어있는 스트림

Stream.builder()

Stream.generate()

public static<T> Stream<T> generate(Supplier<? extends T> s) {
    Objects.requireNonNull(s);
    return StreamSupport.stream(
            new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
}

.generate()는 순서 없는 무한한 스트림을 반환하는 메서드 입니다.
매개변수인 Supplier<? extends T> s는 인자는 없고 리턴값만 있는 함수영 인터페이스 입니다.
(여기서 Supplier란? 여기서 알아볼 수 있습니다.)

@Test
void generate_생성하기() {
  Stream<String> generatedStream = Stream.generate(() -> "hoit").limit(5);

  System.out.println("generatedStream: " + generatedStream
    .collect(Collectors.joining(", "))
  );
}

실행 결과는 아래와 같습니다.

generatedStream: hoit, hoit, hoit, hoit, hoit

그리고 역시나 위의 구문에서 limit()를 빼고 실행을 했더니 OutOfMemoryError가 발생했습니다.

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space...

Stream.iterate()

public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
  ...
}

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}
@Test
void iterate_생성하기() {
  Stream<Integer> iteratedStream = Stream.iterate(30, n -> n + 2).limit(5);

  System.out.println("iteratedStream: " + iteratedStream
    .map(Objects::toString)
    .collect(Collectors.joining(", "))
  );
}

기본 타입형 스트림

@Test
void 기본타입형_생성하기() {
  // 기본타입 스트림 생성 가능
  // range vs rangeClosed?
  //  - 두번째 인자인 종료지점이 포함되느냐 안되느냐의 차이
  IntStream intStream = IntStream.range(1, 5);			// 1, 2, 3, 4
  LongStream longStream = LongStream.rangeClosed(1, 5);	// 1, 2, 3, 4, 5

  // 제네릭을 사용하지 않아 불필요한 auto-boxing 이 일어나지 않습니다.
  // 필요에 의해 boxed 메서드를 통해 boxing 가능!
  Stream<Integer> boxedIntStream = IntStream.range(1, 5).boxed();

  // Random 을 통해 난수를 쉽게 만들어 후속 작업도 가능합니다.
  DoubleStream doubles = new Random().doubles(3);

  // 각각 출력...
}

🤔 결과는?

intStream: 1, 2, 3, 4
longStream: 1, 2, 3, 4, 5
boxedIntStream: 1, 2, 3, 4
doubles: 0.029882971419529336, 0.6801198304654672, 0.8472832577137249

문자열 String

@Test
void 문자열_String으로_생성하기() {
  // String 의 chars() 메서드로 각 문자(char)를 IntStream 으로 변환 가능합니다.
  IntStream charsStream = "Stream".chars();

  // 정규표현식을 활용해서, 각 요소들을 스트림으로 만들 수도 있습니다.
  Stream<String> stringStream = Pattern.compile(", ").splitAsStream("Eric, Elena, Java");

  // 각각 출력..
}

🤔 결과는?

charsStream: 83, 116, 114, 101, 97, 109
stringStream: Eric, Elena, Java

파일 스트림

자바 NIO의 Files 클래스의 lines 메서드는 해당 파일의 각 라인을 String 타입의 스트림으로 변환
([자바 NIO] 자바는 어디서 느릴까? 도 읽어 보면 좋을듯한...?)

@Test
void 파일_스트림_생성하기() {
  try {
    Stream<String> lineStream = Files.lines(Paths.get("file.txt"), StandardCharsets.UTF_8);
  } catch (IOException e) {
    throw new RuntimeException(e);
  }
}

병렬 스트림 Pararell Stream

@Data
@AllArgsConstructor
class Product {
  String name;
  int amount;
}

@Test
void 병렬_스트림_생성하기() {
  List<Product> productList = Arrays.asList(
    new Product("새콤달콤", 30),
    new Product("새우깡", 120),
    new Product("포카칩", 120),
    new Product("칸쵸", 300)
  );
  Stream<Product> parallelStream = productList.parallelStream();

  boolean isParallel = parallelStream.isParallel();
  System.out.println("parallelStream - 병렬 여부 확인: " + isParallel);

  boolean isMany = parallelStream
    .map(product -> {
      System.out.println(product);
      return product.getAmount() * 10;
    })
    .anyMatch(amount -> {
      System.out.println(amount);
      return amount < 200;
    });
  System.out.println("200원 넘는 제품이 존재하는가: " + isMany);

  Stream<String> parallelStreamByArray = Arrays.stream(new String[] {"새우깡", "새콤달콤"}).parallel();

  IntStream intStream = IntStream.range(1, 150).parallel();
  isParallel = intStream.isParallel();
  System.out.println("intStream - 병렬 여부 확인: " + isParallel);

  intStream = intStream.sequential();
  isParallel = intStream.isParallel();
  System.out.println("intStream - 병렬 여부 확인: " + isParallel);
}
parallelStream - 병렬 여부 확인: true
Ex1_Create.Product(name=포카칩, amount=120)
Ex1_Create.Product(name=새콤달콤, amount=30)
300
Ex1_Create.Product(name=새우깡, amount=120)
1200
Ex1_Create.Product(name=칸쵸, amount=300)
3000
1200
200원 넘는 제품이 존재하는가: false
intStream - 병렬 여부 확인: true
intStream - 병렬 여부 확인: false

스트림 연결하기

Stream.concat()을 이용하면 두개의 스트림을 연결해서 새로운 스트림을 만들 수 있습니다.

@Test
void 스트림_연결하기() {
  Stream<String> stream1 = Stream.of("Java", "Scala", "Groovy");
  Stream<String> stream2 = Stream.of("Python", "Go", "Swift");
  Stream<String> concat = Stream.concat(stream1, stream2);

  // 출력...
}

🏃 출력 결과는 아래와 같습니다.

concat: Java, Scala, Groovy, Python, Go, Swift

✨ 참고

profile
BackEnd 개발 일기

0개의 댓글