[TIL] 4일차 스트림

김지수·2024년 4월 24일

TIL

목록 보기
4/53

스트림이란?

자바에서 스트림은 데이터를 다루는데 사용되는 추상화된 개념이다. 스트림은 데이터 소스로부터 데이터를 읽어들이거나 데이터를 쓰는 작업을 수행할 수 있다. 주로 컬렉션, 배열 또는 파일과 같은 다양한 데이터 소스를 처리할 때 사용된다.
자바8에서 소개된 스트림 API는 함수형 프로그래밍의 개념을 도입하여 컬렉션 데이터를 처리하는 방식을 개선했다. 스트림은 데이터를 일련의 연속된 요소로 취급하며 이를 통해 데이터를 처리하는 여러 유용한 작업을 수행할 수 있다. 스트림은 요소의 시퀀스를 병렬로 처리할 수 있어서 대량의 데이터를 효율적으로 처리할 수 있다

스트림의 장단점

장점

  1. 간결하고 가독성이 높은 코드
    스트림 API는 함수형 프로그래밍의 개념을 활용하므로 코드가 간결하고 가독성이 높다. 연산을 연결하여 처리할 수 있어 코드의 흐름을 명확하게 표현할 수 있다.
  2. 병렬 처리 지원
    스트림은 요소를 병렬로 처리할 수 있는 기능을 제공하므로 대용량 데이터를 효율적으로 처리할 수 있다. 이는 멀티코어 프로세서를 활용하여 성능을 향상시킬 수 있는 장점으로 작용한다.
  3. 유연한 연산 체인
    중간 연산과 최종 연산을 조합하여 다양한 작업을 수행할 수 있다. 이는 필요에 따라 연산을 추가하거나 변경하여 동적으로 처리 과정을 조정할 수 있는 유연성을 제공한다.
  4. 재사용성
    스트림은 한 번 생성된 후 여러 번 사용될 수 있으므로 코드의 재사용성을 높여준다.

단점

  1. 학습 곡선
    스트림 API는 함수형 프로그래밍의 개념을 포함하고 있기 때문에 초보자에게는 학습 곡선이 높을 수 있다. 람다식, 함수형 인터페이스 등의 개념을 이해해야 하며 이에 익숙해지는 데 시간이 걸릴 수 있다.
  2. 성능 문제
    스트림을 잘못 사용하면 성능 문제가 발생할 수 있다. 예를 들어, 순차적으로 처리해야 하는 작업을 병렬 처리하는 경우 등이 있다. 이러한 성능 문제를 방지하기 위해 적절한 연산을 선택하고 사용해야 한다.

스트림의 중간연산과 최종연산

중간 연산

filter(Predicate)
주어진 조건을 만족하는 요소만을 포함하는 스트림을 반환한다.
map(Function)
각 요소에 대해 주어진 함수를 적용하여 그 결과로 이루어진 새로운 스트림을 반환한다.
flatMap(Function)
각 요소에 대해 주어진 함수를 적용하고, 각 결과 스트림을 하나의 스트림으로 연결하여 반환한다.
distinct()
중복 요소를 제거한 스트림을 반환한다.
sorted()
요소를 정렬한 스트림을 반환한다.
limit(long)
처음에 주어진 개수만큼의 요소로 제한된 스트림을 반환한다.
skip(long)
처음에 주어진 개수만큼의 요소를 건너뛴 후 남은 요소로 이루어진 스트림을 반환한다.

최종 연산

forEach(Consumer)
각 요소에 대해 주어진 동작을 수행한다..
count()
스트림의 요소 개수를 반환한다..
collect(Collector)
스트림의 요소를 수집하여 새로운 컬렉션을 생성한다.
reduce(BinaryOperator)
스트림의 요소를 하나의 값으로 줄여준다.
min(Comparator)
스트림에서 최소값을 찾아 반환한다.
max(Comparator)
스트림에서 최대값을 찾아 반환한다.
anyMatch(Predicate)
주어진 조건을 만족하는 요소가 하나라도 있는지 검사한다.
allMatch(Predicate)
모든 요소가 주어진 조건을 만족하는지 검사한다.
noneMatch(Predicate)
주어진 조건을 만족하는 요소가 없는지 검사한다.
findAny()
임의의 요소를 찾아 반환한다.
findFirst()
스트림의 첫 번째 요소를 반환한다.

스트림은 중간 연산과 최종 연산으로 구성 된다. 중간 연산은 스트림의 요소를 변환하거나 필터링 하는 작업을 수행하며 최종연산은 최종 결과를 생성하거나 스트림을 종료하는 작업을 수행한다.

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class Main {

  public static void main(String[] args) {
    List<Book> bookList = Arrays.asList(
        new Book(1L, "모두의 딥러닝", "조태호", "IT", 21600),
        new Book(2L, "이득우의 게임 수학", "이득우", "IT", 40500),
        new Book(3L, "자바 웹 개발 워크북", "구멍가게 코딩단", "IT", 31500),
        new Book(4L, "실전 시계열 분석", "에일린 닐슨", "IT", 34200),
        new Book(5L, "데이터 분석가의 숫자유감", "권정민", "IT", 14400),
        new Book(6L, "스프링 부트 실전 활용 마스터", "그렉 턴키스트", "IT", 25200),
        new Book(7L, "오늘부터 IT를 시작합니다", "고코더", "IT", 16200),
        new Book(8L, "그림으로 이해하는 인지과학", "기타하라 요시노리", "IT", 16200),
        new Book(9L, "괜찮아, 그 길 끝에 행복이 기다릴 거야", "손미나", "여행", 17100),
        new Book(10L, "여행의 이유", "김영하", "여행", 12150),
        new Book(11L, "여행의 시간", "김진애", "여행", 16200),
        new Book(12L, "로봇 시대 살아남기", "염규현", "역사", 14850),
        new Book(13L, "경제 전쟁의 흑역사", "이완배", "역사", 15750),
        new Book(14L, "100가지 동물로 읽는 세계사", "사이먼 반즈", "역사", 29700),
        new Book(15L, "k 배터리 레볼루션", "박순혁", "경제", 17100),
        new Book(16L, "정하준의 경제학 레시피", "장하준", "경제", 16200),
        new Book(17L, "레버리지", "롭 무어", "경제", 16200)
    );
    System.out.println("------------카테고리가 여행인 책 제목 조회------------");
    List<String> 여행 = bookList.stream()
                                .filter(book -> book.getCategory().equals("여행"))
                                .map(Book::getBookName)
                                .collect(Collectors.toList());
    여행.forEach(System.out::println);

    System.out.println("------------가격이 16200원 이하인 책 제목 조회 ------------");
    List<String> 이하 = bookList.stream()
                                .filter((book) -> book.getPrice() <= 16200)
                                .map(Book::getBookName)
                                .collect(Collectors.toList());
    이하.forEach(System.out::println);

    System.out.println("---책 제목에 \"경제\"라는 용어가 들어간 책 제목 조회------");

    List<String> 경제 = bookList.stream()
                                .filter(book -> book.getBookName().contains("경제"))
                                .map(Book::getBookName)
                                .collect(Collectors.toList());
    경제.forEach(System.out::println);

    System.out.println("------------가격이 가장 비싼 책 가격 조회------------");

    double maxPrice = bookList.stream()
                              .max(Comparator.comparing(Book::getPrice))
                              .get().getPrice();
    System.out.println(maxPrice);

    System.out.println("----------카테고리가 IT인 책들의 가격 합 조회-------------");

    double sum = bookList.stream()
                          .filter(book -> book.getCategory().equals("IT"))
                          .mapToDouble(Book::getPrice)
                          .sum();

    System.out.println(" IT 책값 모두 가격은 : " + sum);

    System.out.println("--카테고리가 IT인 책들의 가격을 40% 할인하여 새로운 책 리스트 만들기");

    List<Book> discountedBookList = bookList.stream()
        .filter(book -> book.getCategory().equals("IT"))
        .map(book -> {
          double discountedPrice = book.getPrice() * 0.6;
          book.setPrice(discountedPrice);
          return book;
        })
        .collect(Collectors.toList());

    for (Book book : discountedBookList) {
      System.out.println("할인된 책 제목: " + book.getBookName());
      System.out.println("할인된 책 가격: " + book.getPrice() + "\n");
    }
    for (Book book : bookList) {
      System.out.println(book.getBookName());
      System.out.println("원래 가격: " + book.getPrice());
    }
    System.out.println("------------------------");
  }
}

오늘의 회고

긍정적인 점
stream에 대해서 공부하는데 시간을 썼다. 자바의 스트림API에 대해서 지식을 얻었고 이를 활용하여 코드를 작성하는 방법을 배웠다. 나중에 프로젝트나 문제 해결에 도움이 될 것으로 기대된다.
발전해야 할 점
스트림에 대해서 개념을 이해하고 활용하는데 과정에서 많은 연습이 필요할 것 같다. 숙련도를 높여야 할 것 같다.
앞으로의 계획
내일은 시간을 더 효율적으로 활용하고 공부한 내용을 연습을 적용해봐야겠다.

profile
서툴고 부족한 점이 많지만, 배우고 발전하며 성장하기 위해 노력하겠습니다.

0개의 댓글