[Java(자바)] Stream(스트림)

2024. 5. 21. 12:16·Java/Java

자바 스트림

Java 8부터 추가된 기술로 람다를 활용해 배열과 컬렉션을 함수형으로 간단하게 처리할 수 있는 기술로, 많은 수의 데이터를 다룰 때 유용함

기존 방식

  • for문과 Iterator를 사용
  • 코드가 길어져서 가독성과 재사용성이 떨어짐
  • 데이터 타입(List, Set 등)마다 다른 방식으로 다뤄야 함

스트림

  • 데이터 소스를 추상화함
    • 데이터 소스에 상관없이 모두 같은 방식으로 다룰 수 있으므로 코드의 재사용성이 높아짐
  • 데이터를 다루는 데 자주 사용되는 메소드를 정의해 놓음

특징

  • 데이터 소스를 변경하지 않는다
  • 한번 사용하면 닫혀서 다시 사용할 수 없는 일회용이다
  • 반복문을 메서드의 내부에 숨길 수 있다
  • 데이터 소스를 스트림으로 변환한 후 여러 번의 중간연산과 마지막의 최종 연산을 통해 다룰 수 있다
  • 최종 연산이 수행되기 전까지는 중간 연산이 수행되지 않는다
  • 데이터 소스의 요소를 기본형으로 다루는 스트림, IntStream, LongStream, DoubleStream이 제공된다
    • 오토박싱&언박싱의 비효율을 줄인다
    • 숫자의 경우 더 유용한 메서드를 Stream<T>보다 더 많이 제공한다
  • 내부적으로 fork&join 프레임웍을 이용해서 자동적으로 연산을 병렬로 수행한다(멀티 쓰레드)
    • 병렬 연산O - parallel()
    • 병렬 연산X (기본값) - sequential()

스트림 사용

스트림 생성

  • Collection의 자손인 List, Set을 구현한 컬렉션 클래스들은 stream()으로 스트림 생성
List<Integer> list = Arrays.asList(1,2,3,4,5); // 가변인자
Stream<Integer> intStream = list.stream(); // list를 소스로 하는 컬렉션 생성
intStream.forEach(System.out::println); // stream의 모든 요소 출력
  • 객체 배열로부터 스트림 생성
// 첫번째 방법
Stream<String> strStream1 = Stream.of("a", "b", "c");
// 두번째 방법
Stream<String> strStream2 = Stream.of(new String[]{"a", "b", "c"});
// 세번째 방법
String[] strArr = new String[]{"a", "b", "c"};
Stream<String> strStream3 = Stream.of(strArr);
// 네번째 방법
Stream<String> strStream4 = Arrays.stream(strArr);
  • 람다식 - iterate(), generate()
    • 기본형 스트림 타입의 참조변수로 다루면 에러
// iterate(T seed, UnaryOperator f) 단항 연산자
Stream<Integer> intStream7 = Stream.iterate(0, n -> n + 2);
intStream7.limit(10).forEach(System.out::println);

// generate(Supplier s) : 주기만 하는 것. 입력X, 출력O
Stream<Integer> oneStream = Stream.generate(() -> 1);
oneStream.limit(10).forEach(System.out::println);

스트림의 중간연산

  • 스트림 자르기 - skip(), limit()
IntStream intStream8 = IntStream.rangeClosed(1,10); // 1~10의 요소를 가진 스트림
intStream.skip(3).limit(5).forEach(System.out::print); // 45678
  • 스트림의 요소 걸러내기 - filter(), distinct()
IntStream intStream9 = IntStream.of(1,2,2,3,3,3,4,5,5,6);
intStream9.distinct().forEach(System.out::print); // 123456

IntStream intStream10 = IntStream.rangeClosed(1, 10); // 1~10
intStream10.filter(i -> i%2 == 0).forEach(System.out::print); // 246810
  • 정렬 - sorted()
    • 지정된 Comparator로 스트림 정렬
Stream<String> strStream = Stream.of("dd", "aaa", "CC", "cc", "b");
strStream.sorted().forEach(System.out::print); // CCaaabccdd
  • 반환 - map()
    • 스트림의 요소에 저장된 값 중에 원하는 필드만 뽑아내거나 특정 형태로 변환할 때 사용
List<String> list2 = Arrays.asList("hello", "java", "world");
list2.stream().map(s -> s.toUpperCase()).forEach(System.out::println);
  • 조회 - peek()
    • 연산과 연산 사이에 올바르게 처리되었는지 확인
List<Integer> list3 = Arrays.asList(1, 2, 3, 4, 5);
OptionalDouble result = list3.stream()
        .filter(num -> num % 2 == 0)
        .peek(num -> System.out.println(num))
        .mapToInt(num -> num)
        .average();
System.out.println(result);

스트림의 최종연산

  • 리듀싱 - reduce()
    • 스트림의 요소를 줄여나가면서 연산을 수행하고 최종결과를 반환
  1. Identity : 계산을 수행하기 위한 초기값
  2. Accumulator : 각 요소를 계산한 중간 결과를 생성하기 위해 사용하는 누적작업
  3. Combiner : 병렬 스트림에서 나누어 계산된 결과를 하나로 합치기 위해 사용(싱글일 때는 사용하지 않음)
String[] strArr2 = {"Apple", "Banana", "tomato", "watermelon"};
int sum = Stream.of(strArr) // strArr 배열을 스트림으로 변환
                .mapToInt(String::length) // 각 문자열의 길이를 추출. 스트림의 데이터 타입이 IntStream으로 변경
                .reduce(0, (a, b) -> a + b); // IntStream의 모든 요소(문자열 길이)를 합계로 계산

System.out.println(sum); // Output: 27

IntStream intStream = IntStream.of(1,2,2,3,3,3,4,5,5,6);
OptionalInt min = intStream.reduce(Integer::min);
System.out.println(min.getAsInt()); // 1
  • collect()
    • 그룹별 리듀싱이 가능
    • collect()는 Collector를 매개변수로 하는 스트림의 최종연산
    • Collector는 수집(collect)에 필요한 메서드를 정의해 놓은 인터페이스
    • Collectors클래스는 다양한 기능의 컬렉터(Collector를 구현한 클래스)를 제공
Object collect(Collector collector) // Collector를 구현한 클래스의 객체를 매개변수로
Collectors클래스
변환 mapping(), toList(), toSet(), toMap(), toCollection(), …
통계 counting(), summingInt(), averagingInt(), maxBy(), minBy(), summarizingInt()
문자열 결합 joining()
리듀싱 reducing()
그룹화와 분할 groupingBy(), partitioningBy(), collectingAndThen()

스트림을 컬렉션으로 변환

List<String> names = stuStream.map(Student::getName) // Stream<Student>→Stream<String>
    .collect(Collectors.toList()); // Stream<String>→List<String>
ArrayList<String> list = names.stream()
    .collect(Collectors.toCollection(ArrayList::new)); // Stream<String>→ArrayList<String>
Map<String,Person> map = personStream
    .collect(Collectors.toMap(p->p.getRegId(), p->p));// Stream<Person>→Map<String,Person>

스트림의 통계

Collectors 클래스는 그룹별 연산가능

long count = stuStream.count(); // 전체 카운팅
long count = stuStream.collect(counting()); // Collectors.counting() 그룹별 연산 가능

long totalScore = stuStream.mapToInt(Student::getTotalScore).sum(); // IntStream의 sum()
long totalScore = stuStream.collect(summingInt(Student::getTotalScore)); // 그룹별 연산 가능

OptionalInt topScore = studentStream.mapToInt(Student::getTotalScore).max();
Optional<Student> topStudent = stuStream
    .max(Comparator.comparingInt(Student::getTotalScore));
Optional<Student> topStudent = stuStream
    .collect(maxBy(Comparator.comparingInt(Student::getTotalScore))); // 그룹별 연산 가능

스트림을 리듀싱 - reducing()

reduce()는 전체 리듀싱
Collectors.reducing()은 그룹별 리듀싱 가능

IntStream intStream = new Random().ints(1,46).distinct().limit(6);
OptionalInt max = intStream.reduce(Integer::max);  // 전체 리듀싱
Optional<Integer> max = intStream.boxed().collect(reducing(Integer::max)); // 그룹별 리듀싱 가능

long sum = intStream.reduce(0, (a,b) -> a + b); // 전체 리듀싱
long sum = intStream.boxed().collect(reducing(0, (a,b)-> a + b)); // 그룹별 리듀싱 가능

int grandTotal = stuStream.map(Student::getTotalScore).reduce(0, Integer::sum); // 전체 리듀싱
int grandTotal = stuStream.collect(reducing(0, Student::getTotalScore, Integer::sum)); // 그룹별 리듀싱 가능

 

저작자표시 비영리 변경금지 (새창열림)

'Java > Java' 카테고리의 다른 글

[Java(자바)] 오버라이딩과 오버로딩  (0) 2024.05.22
[Java(자바)] JVM(Java Virtual Machine)  (0) 2024.05.12
[Java(자바)] Java 21 - Virtual thread  (0) 2024.05.12
[Java(자바)] 자바의 Thread(쓰레드)  (0) 2024.05.12
[Java(자바)] 메모리 관리와 가비지 컬렉션  (0) 2024.05.12
'Java/Java' 카테고리의 다른 글
  • [Java(자바)] 오버라이딩과 오버로딩
  • [Java(자바)] JVM(Java Virtual Machine)
  • [Java(자바)] Java 21 - Virtual thread
  • [Java(자바)] 자바의 Thread(쓰레드)
주민1호
주민1호
개발/알고리즘 등등
  • 주민1호
    개발바라기별
    주민1호
  • 전체
    오늘
    어제
  • 블로그 메뉴

    • 🏚️
    • 🏷️
    • ✏️
    • ⚙️
    • All (40)
      • Data (0)
        • 💯DASP (0)
        • 💯SQLD (0)
        • 💯ADSP (0)
      • Java (17)
        • Java (11)
        • Spring Framework (6)
      • Python (0)
        • Python (0)
        • Flask (0)
        • TensorFlow (0)
      • JavaScript (1)
        • React (0)
        • Vue (0)
      • Lang (11)
        • C (11)
        • C++ (0)
      • Infra (0)
        • Docker (0)
        • Kubernetes (0)
        • AWS (0)
      • Algorithm (9)
      • 운영체제 (0)
        • Linux (0)
      • Etc. (1)
        • Git (1)
        • Network (0)
        • 컴퓨터과학개론 (0)
        • 멀티미디어시스템 (0)
      • AI (0)
      • Projects (0)
        • 2022 OSSCA (0)
      • Review (0)
      • 회고 (0)
  • hELLO· Designed By정상우.v4.10.3
주민1호
[Java(자바)] Stream(스트림)
상단으로

티스토리툴바