자바 스트림 정리2-스트림 중간연산

Published: by Creative Commons Licence

자바에서 스트림(Stream) 내의 요소를 원하는 형태에 알맞게 가공하는 중간 연산에 대해서 정리하려고 한다. 중간 연산은 반환 값으로 다른 스트림을 반환하기 때문에 이어서 호출하는 메소드 체이닝이 가능하다.

sorted 메소드 중간연산

@Test
void test1(){
    List<Cat> cats = Arrays.asList(
            new Cat(2, "sana"),
            new Cat(3, "momo"),
            new Cat(1, "mina"),
            new Cat(4, "jihyo")
    );

    cats.stream()
            .sorted(Comparator.comparing(Cat::getNumber))
            .forEach(System.out::println);

    System.out.println("====================================================");

    cats.stream()
            .sorted(Comparator.comparing(Cat::getNumber).reversed())
            .forEach(System.out::println);
}

filter 메소드 중간연산

filter 메서드로 스트림 내 요소들을 조건으로 필터링한다. Predicate 인터페이스는 test 추상 메소드를 정의하고 제네릭 형식의 객체를 파라미터로 전달받아 boolean 값을 리턴한다.

@Test
void test2(){
    List<String> list = List.of("a", "bb", "acc", "ddd");

    list.stream()
            .filter(s -> s.startsWith("a"))
            .forEach(System.out::println);


    System.out.println("====================================================");

    list.stream()
            .filter(new Predicate<String>() {
                @Override
                public boolean test(String s) {
                    return s.startsWith("a");
                }
            })
            .forEach(System.out::println);
}

map 메소드 중간연산

map 메소드를 사용하여 스트림 내 요소들을 하나씩 특정 값으로 변환한다.

@Test
void test3(){
    List<String> list = List.of("a", "bb", "acc", "ddd");
    list.stream()
            .map(s -> s.toUpperCase(Locale.ROOT))
            .forEach(System.out::println);

    System.out.println("====================================================");

    list.stream()
            .map(new Function<String, String>() {
                @Override
                public String apply(String s){
                    return s.toUpperCase(Locale.ROOT);
                }
            }).forEach(System.out::println);
}

flatMap 메소드 중간연산

2차원 배열과 같은 중첩 구조를 한단계 없애고 단일 원소 스트림으로 변환한다.

@Test
void test4(){
    List<String> list1 = List.of("a1", "a2");
    List<String> list2 = List.of("b1", "b2");
    List<List<String>> newList = List.of(list1, list2);

    newList.stream()
            .flatMap(new Function<List<String>, Stream<String>>() {
                @Override
                public Stream<String> apply(List<String> strings) {
                    return strings.stream();
                }
            }).collect(Collectors.toList())
            .forEach(System.out::println);

    System.out.println("====================================================");

    newList.stream()
            .flatMap(list -> list.stream())
            .collect(Collectors.toList())
            .forEach(System.out::println);
}

distinct 메소드 중간연산

@Test
void test5(){

    List<String> strList = List.of("t3", "t1", "t2", "t1", "t4", "t3");
    strList.stream()
            .distinct()
            .forEach(System.out::println);

    System.out.println("====================================================");

    Foo foo1 = new Foo("111");
    Foo foo2 = new Foo("222");
    Foo foo3 = new Foo("111");
    Foo foo4 = new Foo("444");
    Foo foo5 = new Foo("555");
    List<Foo> objList = List.of(foo1, foo2, foo3, foo4, foo5, foo1, foo2, foo3);

    objList.stream().distinct()
            .forEach(System.out::println);
}

peek 메소드 중간연산

peek 메소드는 원본 스트림에서 요소를 소모하지 않고 중간 연산 사이의 결과를 확인할 때 많이 사용한다. peek 연산은 단말 연산이 수행되지 않으면 실행이 안된다.

@Test
void test6(){
    List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8);
    List<Integer> filterList = list.stream()
            .filter(i -> i > 1 && i < 5)
            .peek(System.out::println)
            .filter(i -> i > 3)
            .peek(System.out::println)
            .collect(Collectors.toList());

    System.out.println("###RESULT###");
    filterList.stream().forEach(System.out::println);
}

limit 메소드 중간연산

스트림 내의 요소 개수를 제한할 때 사용한다.

@Test
void test7(){
    // limit 메서드를 사용하면 스트림 내의 요소 개수를 제한할 수 있습니다.
    List<String> list = List.of("a", "b", "c", "d", "e").stream()
            .limit(3)
            .collect(Collectors.toList());

    System.out.println(list);
}

skip 메소드 중간연산

skip 메소드는 인자로 받은 숫자 만큼의 요소를 제외한 요소의 스트림을 리턴한다.

@Test
void test8() {
    // skip 메서드를 사용하면 스트림 내의 첫 번째 요소부터 인자로 전달된
    // 개수 만큼의 요소를 제외한 나머지 요소로 구성된 새로운 스트림을 리턴합니다.
    List<String> list = Arrays.stream(new String[]{"a", "b", "c", "d", "e"})
            .skip(3)
            .collect(Collectors.toList());

    System.out.println(list);
}

참고

자바 스트림 정리: 2. 스트림의 중간 연산
Java 스트림 Stream (1) 총정리

Github

https://github.com/sisipapa/StreamExample.git