ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java 8 - 3. Stream
    공부일기/Java 8 2020. 12. 16. 16:35

    1. Stream

    연속된 데이터를 처리하는 Operation들의 모음.

    스트림은 데이터를 담고 있는 저장소가 아니며, 스트림으로 처리되는 데이터 소스는 변경되지 않는다.

    오직 한 번만 처리하며 무제한일 수 있다.

    중개 오퍼레이터와 종료 오퍼레이터로 나눌 수 있다.

     

     

    중개 오퍼레이션

    • Stream을 리턴한다.

    • Stateless / Stateful 오퍼레이션으로 더 상세하게 구분할 수도 있다. (대부분은 Stateless지만 distinct나 sorted 처럼 이전 이전 소스 데이터를 참조해야 하는 오퍼레이션은 Stateful 오퍼레이션이다.)

    • filter, map, limit, skip, sorted, ...

     

    종료 오퍼레이션

    • Stream을 리턴하지 않는다.

    • collect, allMatch, count, forEach, min, max, ...

     

    2. Stream API

    걸러내기

    • Filter(Predicate.not())
      ! 사용이 불가능 하기 때문에 Predicate.not()을 사용할 수 있다.

    • 예) 이름이 3글자 이상인 데이터만 새로운 스트림으로 

    package stream;
    
    import java.util.Arrays;
    import java.util.List;
    
    public class practice {
        public static void main(String[] args) {
            List<String> names = Arrays.asList("유비", "관우", "제갈공명", "사마천", "사마의");
    
            names.stream().filter(practice::nameLengthisThree)
                    .forEach(System.out::println);
        }
    
        private static boolean nameLengthisThree(String name) {
            return name.length() == 3;
        }
    }
    
    사마천
    사마의

    아래는 메서드 레퍼런스로 변경한 코드 결과는 동일하다.

    package stream;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Predicate;
    
    public class practice {
        public static void main(String[] args) {
            List<String> names = Arrays.asList("유비", "관우", "제갈공명", "사마천", "사마의");
    
            names.stream().filter(Predicate.not(practice::name))
                    .forEach(System.out::println);
        }
    
        private static boolean name(String name) {
            return name.length() == 4;
        }
    }
    

     

     

    • 예) 이름이 4글자가 아닌 데이터만 새로운 스트림으로
    package stream;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Predicate;
    
    public class practice {
        public static void main(String[] args) {
            List<String> names = Arrays.asList("유비", "관우", "제갈공명", "사마천", "사마의");
    
            names.stream().filter(Predicate.not(name->name.length()==4))
                    .forEach(System.out::println);
        }
    }
    
    유비
    관우
    사마천
    사마의

    마찬가지로 아래는 위의 코드를 메서드 레퍼런스를 사용해 변경한 코드.

    package stream;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Predicate;
    
    public class practice {
        public static void main(String[] args) {
            List<String> names = Arrays.asList("유비", "관우", "제갈공명", "사마천", "사마의");
    
            names.stream().filter(Predicate.not(practice::nameLengthisNotFour))
                    .forEach(System.out::println);
        }
    
        private static boolean nameLengthisNotFour(String name) {
            return name.length() == 4;
        }
    }
    

     

     

    변경하기

    • Map(Function) 또는 FlatMap(Function)

    package stream;
    
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.List;
    import java.util.stream.Collectors;
    
    public class practice {
        public static void main(String[] args) {
            List<Integer> scores = Arrays.asList(10,20,30,40,50,60,70,80,90,100);
    
            Collection<String> stringScore = scores.stream()
                    .map(score -> score + "")
                    .collect(Collectors.toList());
    
            System.out.println(stringScore);
        }
    }
    

    map()을 이용해 String 타입으로 변환시켜 새로운 리스트에 저장한 예제이다.

    [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

     

    flatmap()은 이중리스트를 스트림으로 보낼 때 각 리스트안의 요소들을 펼쳐 요소 하나하나가 스트림을 거쳐 지나갈 수 있게 만들어 주는 기능이다. 

    package stream;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.List;
    import java.util.stream.Collectors;
    
    public class practice {
        public static void main(String[] args) {
            List<Integer> mathScore = Arrays.asList(10,20,30);
            List<Integer> koreanScore = Arrays.asList(40,50,60);
            List<Integer> engScore = Arrays.asList(70,80,90);
    
            List<List<Integer>> subject = new ArrayList<>();
            subject.add(mathScore);
            subject.add(koreanScore);
            subject.add(engScore);
    
            subject.stream().flatMap(Collection::stream)
                    .forEach(System.out::println);
        }
    }
    
    10
    20
    30
    40
    50
    60
    70
    80
    90

    10 - 90까지 각 과목의 점수를 출력해주는 것을 확인할 수 있다. 이 메소드를 진작 알았더라면 우테코 3주차 미션에서 지하철 노선도 출력할 때 활용할 수 있었을텐데...

     

     

    생성하기

    • generate(Supplier) 또는 Iterate(T seed, UnaryOperator) 

    • 예) 10부터 1씩 증가하는 무제한 숫자 스트림

    package stream;
    
    import java.util.stream.Stream;
    
    public class practice {
        public static void main(String[] args) {
            Stream.iterate(10, i -> i+1)
                    .forEach(System.out::println);
        }
    }
    10
    11
    12
    ...

     

     

    • 예) 랜덤 int 무제한 스트림

    package stream;
    
    import java.util.Random;
    import java.util.stream.Stream;
    
    public class practice {
        public static void main(String[] args) {
            Random random = new Random();
            Stream.iterate(10, i -> random.nextInt() )
                    .forEach(System.out::println);
        }
    }
    
    10
    -860808916
    297488868
    1860616718
    ...

     

     

    제한하기

    • limit(long) 또는 skip(long)
      그렇다면 생성 하는데 제한을 두려면 어떻게 해야 할까?

    • 예) 최대 5개의 요소가 담긴 스트림을 리턴한다.

    package stream;
    
    import java.util.stream.Stream;
    
    public class practice {
        public static void main(String[] args) {
            Stream.iterate(10, i -> i+1)
                    .limit(5)
                    .forEach(System.out::println);
        }
    }
    10
    11
    12
    13
    14

     

    • 예) 앞에서 3개를 뺀 나머지 스트림을 리턴한다.

    package stream;
    
    import java.util.stream.Stream;
    
    public class practice {
        public static void main(String[] args) {
            Stream.iterate(10, i -> i+1)
                    .limit(5)
                    .skip(3)
                    .forEach(System.out::println);
        }
    }
    13
    14

     

    • 예) 10부터 1씩 증가하는 무제한 스트림 중 최대 10개까지만 증가하는 스트림
    package stream;
    
    import java.util.Random;
    import java.util.stream.Stream;
    
    public class practice {
        public static void main(String[] args) {
            Random random = new Random();
            Stream.iterate(10, i -> i+1)
                    .limit(10)
                    .forEach(System.out::println);
        }
    }
    
    10
    11
    12
    ...
    19

     

    • 예) 10부터 1씩 증가하는 무제한 스트림 중 앞의 5개는 제외후 10개까지 증가하는 스트림
    package stream;
    
    import java.util.Random;
    import java.util.stream.Stream;
    
    public class practice {
        public static void main(String[] args) {
            Random random = new Random();
            Stream.iterate(10, i -> i+1)
                    .skip(5)
                    .limit(10)
                    .forEach(System.out::println);
        }
    }
    
    15
    16
    17
    ...
    24
    
    // 10, 11, 12, 13, 14
    // 5개는 skip하고 나머지의 것들을 10개 보여준다.

     

     

    스트림에 있는 데이터가 특정 조건을 만족하는지 확인

    • anyMatch(), allMatch(), nonMatch()

    이 스트림 메소드들은 우테코 과제를 진행하며 자연스럽게 자주 익히게 되었다. 하나라도 일치하는 경우, 전부 일치해야하는 경우, 하나도 일치하지 않는 경우를 의미힌다.

     

    • 예) k로 시작하는 문자열이 있는지 확인한다. (true 또는 false를 리턴한다.)

    package stream;
    
    import java.util.Arrays;
    import java.util.List;
    
    public class practice {
        public static void main(String[] args) {
            List<String> names = Arrays.asList("kim", "lee", "park", "kang");
    
            boolean result = names.stream().anyMatch(name -> name.startsWith("k"));
            System.out.println(result);
        }
    }
    true

     

     

    • 예) 스트림에 있는 모든 값이 10보다 작은지 확인한다.

    package stream;
    
    import java.util.Arrays;
    import java.util.List;
    
    public class practice {
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(1,3,5,10,15,20);
    
            boolean result = numbers.stream().allMatch(n -> n<10);
            System.out.println(result);
        }
    }
    false

     

    • 예) 스트림의 값 중 100이 있는지 확인한다.
    package stream;
    
    import java.util.Arrays;
    import java.util.List;
    
    public class practice {
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(1,3,5,10,15,20);
    
            boolean result = numbers.stream().noneMatch(n -> n==100);
            System.out.println(result);
        }
    }
    true

     

    개수 세기

    • count()

    • 예) 10보다 큰 수의 개수를 센다.

    package stream;
    
    import java.util.Arrays;
    import java.util.List;
    
    public class practice {
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(1,3,5,10,15,20);
    
            long count = numbers.stream()
                    .filter(number -> number>10)
                    .count();
    
            System.out.println(count);
        }
    }
    2

    반환 타입이 long인 것을 주의하자!!

     

     

    스트림을 데이터 하나로 뭉치기

    • reduce(identity, BiFunction), collect(), sum(), max() 

    • 예) 모든 숫자 합 구하기

    package stream;
    
    import java.util.Arrays;
    import java.util.List;
    
    public class practice {
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(1,3,5,10,15,20);
    
            System.out.println(numbers.stream().mapToInt(i->i).sum());
        }
    }
    54

     

    • 예) 모든 데이터를 하나의 List 또는 Set에 옮겨 담기

    package stream;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Collectors;
    
    public class practice {
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(1,3,5,10,15,20);
    
            List<Integer> numList = numbers.stream().collect(Collectors.toList());
            System.out.println(numList);
        }
    }
    [1, 3, 5, 10, 15, 20]

     

     

    package stream;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Set;
    import java.util.stream.Collectors;
    
    public class practice {
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(1,3,5,10,15,20);
    
            Set numList = numbers.stream().collect(Collectors.toSet());
            System.out.println(numList);
        }
    }
    [1, 3, 20, 5, 10, 15]

     

     

     

Designed by Tistory.