본문 바로가기

개발지/Today I learn

[0830] 자바 스트림 (스트림 파이프라인 - 2. 스트림의 중간 연산)

#스트림 파이프라인 - 2. 스트림의 중간 연산

- 중간 연산이란 생성한 스트림에서 데이터 소스를 가공하는 과정이다.

- 중간 연산자들 중에 빈번하게 사용되는 것은 필터링, 매핑, 정렬 등이 있다.

 

- 필터링( filter() , distinct() )

  ▪ 조건에 맞는 데이터만 들어오도록 정제하는 역할의 중간 연산자

  ▪ filter() : Stream에서 조건에 맞는 데이터를 정제하여 더 작은 컬렉션을 만든다.

                조건은 람다식을 사용하여 정의한다.

  ▪ distinct() : Stream의 요소들에 중복된 데이터가 존재하는 경우, 중복을 제거한다.

public class FilteringExample {
    public static void main(String[] args) throws Exception {
        
        List<String> countrys = Arrays.asList("조선", "신라", "백제", "고구려", "고려", "조선"}
        
        countrys.stream() // (스트림 생성)
            .distinct() // 중복 제거 (중간연산)
            .forEach(element -> System.out.println(element));
        System.out.println(); // 최종 연산 후 스트림 닫힘
        
        countrys.stream() // 새 스트림 생성
            .filter(element -> element.startsWith("고")) // '고'로 시작하는 요소만 필터링
            .forEach(element -> System.out.println(element));
        System.out.println();
        
        countrys.stream() // 새 스트림 생성
            .distinct()
            .filter(element -> element.startsWith("조"))
            .forEach(element -> System.out.println(element));
        System.out.println();
    }
}

// 출력값
조선
신라
백제
고구려
고려

고구려
고려

조선

 

-  매핑 ( map() )

  ▪ 원하는 필드만 추출하거나 특정 형태로 변환할 때 사용한다.

  ▪ filter() 마찬가지로 값을 변환하기 위하 조건을 람다식으로 정의한다.

public class IntermediateOperationExample {
    public static void main(String[] args) {
        
        List<String> animals = Arrays.asList("tiger", "lion", "dog");
        animals.stream()
            .map(element -> element.toUpperCase()) // 요소들을 대문자로 바꾼 값을 스트림으로 반환
            .forEach(element -> System.out.println(element));
             
        List<Integer> numlist = Arrays.asList(2, 5, 6, 8); // 요소에 4를 곱한 값을 스트림으로 반환
        list.stream().map(number -> number * 4).forEach(System.out::println);
            
    }
}

//출력값
TIGER
LION
DOG

8
20
24
32

 

  ▪ flatMap() 을 통한 플래트닝(이차이상의 배열에서 중첩 구조를 제거하고 단일 컬렉션(Stream<String>)으로 만듦)

// 이중배열의 요소를 스트림으로 출력하기
String[][] brandsArray = new String[][]{{"나이키", "아디다스"}, {"유니클로", "탑텐"}};

    Arrays.stream(brandsArray)
       .map(inner -> Arrays.stream(inner))
       .forEach(brand -> brands.forEach(System.out::println));
       
// 출력값
나이키
아디다스
유니클로
탑텐

// flatMap()을 활용한 플래트닝

Arrays.stream(brandsArray).flatMap(Arrays::stream).forEach(System.out::println);

// 출력값
나이키
아디다스
유니클로
탑텐

 

- 정렬 ( sorted() )

  ▪ 정렬할 때 사용하는 중간 연산자

  ▪ sorted() 메서드 () 안에 Comparator 인터페이스의 정의된 static, 디폴트 메서드를 사용하여 정렬할 수 있다.

public class IntermediateOperationExample {
    public static void main(String[] args) {
        
        List<String> countrys = Arrays.as("Korea", "Japan", "China", "USA");
        // 인자값 없는 정렬
        countrys.stream().sorted().forEach(System.out::println));
        
        // 인자값에 Comparator 인터페이스 메서드 사용
        countrys.strea().sorted(Comparator.reverseOrder()).forEach(System.out::println));
    }
}

// 출력값
China
Japan
Korea
USA

USA
Korea
Japan
China

 

- 기타 스트림 중간 연산자들

  ▪ skip(num) : num개의 스트림 요소들을 건너뛴다.

  ▪ limin(num) : 스트림 요소를 num개까지 자른다.

  ▪ peek() : forEach() 와 마찬가지로, 요소들을 순회하며 특정 작업을 수행한다. (peek는 중간 연산자로 여러 번 사용가능)

                 (forEach()는 최종 연산자이다 / peek() 특성으로 인해 코드의 에러를 찾기 위한 디버깅 용도로 활용된다)

public class IntermediateOperationExample {
    public static void main(String[] args) {
    
        // 1~10 범위의 정수로 구성된 스트림 생성
        IntStream intStream = IntStream.rangeClosed(1, 10);
    
        // skip() 앞의 6개의 숫자를 건너뛰고 숫자 4부터 출력
        intStream.skip(6).forEach(System.out::println);
        
        // limit() 앞에서부터 3개의 숫자만 출력
        intStream.limit(3).forEach(System.out::println);
        
        // peek() 홀수만 필터링하여 합계 구하기
        int sum = intStream.filter(element -> element % 2 == 1)
            .peek(System.out::println)
            .sum();
            
        System.out.println("합계 = " + sum);
    }
}

출력값
7
8
9
10

1
2
3

1
3
5
7
9
합계 = 25