Java

[Java] Stream

삶_ 2022. 6. 27. 13:46

 

 

Stream

  • 다양한 데이터소스(컬렉션/배열..)를 표준화된 방법으로 다루기 위한 것
  • 병렬 처리가 쉬움 (연산을 병렬로 수행)
Stream<Integer> intStream = list.stream(); //컬렉션
Stream<String> strStream = Stream.of(new String[]{"a","b","c"}) //배열

1. 스트림만들기
2. 중간연산 여러번하기
3. 최종연산
  • 중간연산
    • 연산결과가 스트림인 연산. 여러번 적용가능
    • 걸러내기라고 보면 됨
  • 최종연산
    • 연산결과가 스트림이 아닌 연산. 단 한번만 적용가능

 

 

스트림의 특징

  • 데이터를 읽기만 하고 변경하지 않음

  • 일회용 (최종연산 후 필요하면 다시 스트림을 생성해야함)

  • 최종 연산 전까지 중간연산이 수행되지 않음 (지연된 연산)
    • 따라서 아래같은 코드가 가능해짐

  • 작업을 내부 반복으로 처리함

 

 

 

 

스트림 생성

컬렉션

  • Stream<T> Collection.stream()
  • List<Integer> list = Arrays.asList(1,2,3,4,5);
    Stream<Integer> intStream = list.stream();

 

배열

  • nt[] arr = {1,2,3,4,5};
    Stream<Integer> intStream = Arrays.stream(arr); 혹은
    Stream<Integer> intStream = Stream.of(arr);  //다양하게 됨
  • IntStream intStream = IntStream.of(arr); 혹은
    IntStream intStream = Arrays.stream(arr);

 

특정 범위의 정수

  • IntStream intStream = IntStream.range(시작인덱스, 끝인덱스 포함X);
  • IntStream intStream = IntStream.rangeClosed(시작인덱스, 끝인덱스도 포함);

 

람다식

  • iterate(), generate()
    • 람다식을 매개변수로 받아, 이 람다식에 의해 계산되는 값들을 요소로 하는 무한 스트림 생성
    • generate() 는 iterate() 와 달리, 이전 결과를 이용해서 다음요소를 계산하지 않음
    • IntStream 처럼 기본형 스트림 타입의 참조변수로 다룰 수 없음
  • Stream<Double> randomStream = Stream.generate(Math::random);

 

그외

  • 빈 스트림
    • Stream emptyStream = Stream.empty();  //비어있는 스트림 생성. null 보단 이 방법 이용하기!
  • 두 스트림의 연결
    • concat()
    • Stream<String> strs1 = Stream.of(str1);
      Stream<String> strs2 = Stream.of(str2);
      Stream<String> result = Stream.concat(strs1,strs2);  // 두 스트림을 하나로 연결

 

 

 

 

 

스트림의 연산 - 중간연산

  • 같은걸 중복으로 쓸수있음

 

skip(), limit()

forEach()

  • 변수에 컬렉션 등을 넣고 나열하는것
  • collection.forEach(변수 -> 반복처리(변수))
skip(n) //앞에서부터 n개 건너뛰기
limit(n) //n 이후의 요소는 잘라냄

IntStream intStream = IntStream.rangeClosed(1, 10);  //12345678910 (10포함)
intStream.skip(3).limit(5).forEach(System.out::print);  //45678

 

filter(), distinct()

filter(Predicate<? super T> n)  //조건에 맞지않는 요소 제거
Stream<T> distinct()  //중복 제거

IntStream intStream = IntStream.rangeClosed(1,10);
intStream.filter(i->i%2==0).forEach(System.out::print); //2의배수만 뽑기. 246810


IntStream intStream = IntStream.of(1,2,2,3,3,3,4,5,5,6);
intStream.distinct().forEach(System.out::print);  //123456. 중복제거

 

sorted()

  • sorted()  //내림차순 정렬
  • sorted((Comparator...)) //()에 있는 기준으로 정렬

 

Comparator

  • Comparator의 comparing()으로 정렬기준을 제공
  • sorted의 반환타입이 comparator이다
// 반별로 정렬
studentStream.sorted(Comparator.comparing(Student::getBan)).forEach(System.out::println)
  • 정렬기준이 많을때는, thenComparing()을 사용
//추가 정렬 기준을 제공할 때는 thenComparing()을 사용
thenComparing(Comparator<T> other)
thenComparing(Function<T, U> keyExtractor)
thenComparing(Function<T, U> keyExtractor, Comparator<U> keyComp)

studentStream.sorted(Comparator.comparing(Student::getBan)  //반별로 정렬
						.thenComparing(Student::getTotalScore)  //총점별로 정렬
                        .thenComparing(Student::getName))  //이름별로 정렬
                        .forEach(System.out::println);

 

map()

  • 스트림의 요소 변환하기 (Function 을 사용)
  • 원하는 필드만 뽑거나, 특정 형태로 변환해야 할 때 사용
  • mapToInt(), mapToLong(), mapToDouble()
    • 스트림의 값을 int형, Long형, Double형으로 변환할때
    • Stream<String> -> IntStream
// file -> String 으로 변환하기 (map() 이용!)
Stream<File> fileStream = Stream.of(new File("Ex1.java"), new File("Ex1"))
	new File("Ex1.bak"), new File("Ex2.java");

//map()으로, Stream<File> 을 Stream<String> 으로 변환
Stream<String> filenameStream = fileStream.map(File:getName);
filenameStream.forEach(System.out::println);

 

 

 

peek()

  • 스트림의 요소를 소비하지 않고 조회해줌(출력해줌)
  • 출력용이라고 보면 됨 (forEach()문이랑 비슷함)

 

flatmap()

  • 스트림의 스트림을 스트림으로 변환
  • 스트림의 요소가 배열일때, 예를들어 Stream<T[]> 를 Stream<T> 로 바꾸기
Stream<String[]> strArrStrm = Stream.of(new String[]{...},
					new String[]{...});
                                        
// 스트림의 스트림 (map을 이용) -> 스트림을 배열로 바꿈 (스트림 해제) -> 스트림<스트림<String>>
// 이러면 결국 스트림 내에 있기 때문에 또 스트림으로 출력됨(스트림의 스트림 -> 스트림)
Stream<Stream<String>> strStrStrm = strArrStrm.map(Arrays::stream);


// 여러개의 문자열 배열을 -> 하나의 문자열 배열로 바꾸고자 할때
{"..",".."},{"..",".."} 이런 배열을
"..", "..", "..", ".." 이렇게 바꿀때
// flatMap() 을 이용!

Stream<String> strStrStrm = strArrStrm.flatmap(Arrays::stream);

 

 

 

 

 

스트림의 연산 - 최종연산

 

 

foreach()

  • 스트림의 요소를 소모하는 최종연산
  • 출력하는 용도로 많이 씀

 

allMatch(), anyMatch(), noneMatch()

  • 스트림의 요소에 의해 지정된 조건에 모든 요소가 일치하는 지
  • allMatch() : 모두 만족하는지
  • anyMatch() : 하나라도 만족하는지
  • noneMatch() : 모두 만족하지 않는지

 

findFirst(), findAny()

  • findFirst() : 스트림의 요소 중 첫번째로 조건을 만족하는 값 반환
  • findAny() : 스트림의 요소 중 조건을 만족하는 것 중 아무거나 반환

 

count(), sum(), average(), max(), min()

  • 스트림의 요소에 대한 통계정보를 얻음
  • 요소 총 수, 합, 평균, 최대값, 최소값

 

reduce()

  • 스트림의 요소를 줄여나가면서 연산을 수행하고 최종결과 반환

 

 

 

출처

자바의 정석