JAVA - Stream

Seongjin Jo·2023년 1월 2일
0

JAVA

목록 보기
3/5

Stream


Stream 특징

자바 8 에서 추가한 스트림은 람다를 활용할 수 있는 기술 중 하나이다.
스트림은 '데이터의 흐름'이다. 배열 또는 컬렉션의 인스턴스에 함수 여러 개를 조합해서
원하는 결과를 필터링하고 가공된 결과를 얻을 수 있다. 또한 람다를 이용해서 코드의 양을 줄이고
간결하게 표현할 수 있다. 즉, 배열과 컬렉션을 함수형으로 처리할 수 있다.

Stream 사용 순서

1.생성하기 ( Array, Collection )
2.가공하기 ( Filter , Map , Sort , Distinct 등등 )
3.결과만들기 ( 최대-최소-평균 연산 , 합-카운트 , 데이터 수집 연산(collect) 처리 , 특정 조건 검사 , 반복문 )

전체 -> 맵핑 -> 필터링1 -> 필터링2 -> 결과만들기 -> 결과물

1.생성하기

( 컬렉션 스트림 생성 )

  • List list = Arrays.asList("a","b","c");
  • Stream stream = list.stream();

( 배열 스트림 생성 )

  • String[] arr = new String[] {"a","b","c"};
  • Stream stream = Arrays.stream(arr);

( 객체 배열 스트림 생성 )

  • Stream.of("a", "b", "c");
  • Stream.of(new String[]{"a", "b", "c"});
  • Arrays.stream(new String[]{"a", "b", "c"});
  • Arrays.stream(new String[]{"a", "b", "c"}, startIndex, EndIndex+1);

( 람다식 iteratio(), generate(); )

  • Stream.iterate(0, n->n+2); //0, 2, 4, ... 무한 스트림
    //generate는 초기값 지정x, 이전 결과와 무관하다.
  • Stream.generate(Math::random);
  • Stream.generate(()->1);

2.가공하기(중간 연산)

  • .distinct() //중복제거
  • .filter(Predicate predicate) //조건에 안 맞는 요소는 제외
  • .limit(long maxSize) //maxSize 이후의 요소는 잘래냄
  • .skip(long n) //앞에서부터 n개 건너뛰기
  • .sorted() //기본 정렬로 정렬
  • .sorted(Comparator comparator) //조건에 맞게 요소 정렬. 추가 정렬 기준을 제공할 때는 thenComparing()사용
  • .map(Function mapper) //스트림의 요소를 변환. ex) map(File::getName), map(s->s.subString(3))
  • .peek(Consumer action) //요소에 작업수행. 보통 중간 작업결과 확인으로 사용. peek(s->System.out.println(s))
  • .flatMap() //스트림의 스트림을 스트림으로 변환 //ex) Stream strStrm=strArrStrm.flatMap(Arrays::stream)

3.결과 만들기

  • void forEach(Consumer<? super T> action) //각 요소에 지정된 작업 수행

  • void forEachOrdered(Consumer<? super T> action) //병렬 스트림의 경우 순서를 유지하며 수행

  • long count() //스트림의 요소 개수 반환

  • Optional max(Comparator<? super T> comparator) //스트림의 최대값 반환

  • Optional min(Comparator<? super T> comparator) //스트림의 최소값 반환

  • Optional findAny() //아무거나 하나 반환. 벙렬 스트림에 사용

  • Optional findFirst() //첫 번째 요소 반환. 순차 스트림에 사용

  • boolean allMatch(Predicate p) //모든 조건을 만족?

  • boolean anyMatch(Predicate p) //조건을 하나라도 만족?

  • boolean noneMatch(Predicate p) //모든 조건을 만족하지 않음?

  • Object[] toArray() //모든 요소를 배열로 반환

  • A[] toArray(IntFunction<A[]> generator) //특정 타입의 배열로 반환

  • Optional reduce(BinaryOperator accumulator) //스트림의 요소를 하나씩 줄여가면서 계산

  • collect( ~ ) //데이터를 변형 등의 처리를 하고 원하는 자료형으로 변환해 줍니다.

Stream 사용 예시

1.Filter

  • if 문이라고 생각하면 될듯
  • 람다식의 리턴값은 boolean. true면 다음 단계 진행, false면 버려짐
classes.stream()
	.filter(c->c.getTitle().startWith("spring"))
	.forEach(c->System.out.println(oc.getId));

2.Map 또는 FlatMap

  • stream을 우리가 원하는 모양의 새로운 스트림으로 변환
 map(File::getName) //각각의 File에서 String name만 새로운 스트림으로
 map(s->s.subString(3)) //string 타입 요소를 짤라서 새로운 스트림으로

3.limit(long) 또는 skip(long)

  • 예) 최대 5개의 요소가 담긴 스트림을 리턴한다.
  • 예) 앞에서 3개를 뺀 나머지 스트림을 리턴한다.
Stream.iterate(10, i->i+1)
        .skip(10)
        .limit(10)
        .forEach(System.out::println)

4.anyMatch(), allMatch(), nonMatch()

  • 예) k를 포함한 문자열이 있는지 확인한다. (true 또는 false를 리턴한다.)
boolean test=javaClasses.stream()
		.anyMatch(oc->oc.getTitle().contains("k"));

5.findFirst() VS findAny()

  • findFirst()는 stream의 순서를 고려해, 가장 앞쪽에 있는 요소를 반환
  • findAny()는 멀티 쓰레드에서 가장 먼저 찾은 요소를 반환. stream의 뒤쪽에 있는 요소가 반환될 수도 있다.

6.reduce()

  • 스트림의 요소를 하나씩 줄여가며 누적연산 수행
  • reduce(초기값, (누적 변수, 요소)-> 수행문)
Integer sum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).reduce((total, y) -> total + y);
System.out.println("sum: " + s); //sum: 55

//초기값을 지정해 줄 수 있다.
Integer sum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).reduce(10, (total, n) -> total + n);
System.out.println("sum: " + sum); //sum: 65

7.collect()

  • Stream의 요소들을 우리가 원하는 자료형으로 변환할 수 있다.
stream.collect(Collectors.toSet()); //set으로 변환
stream.collect(Collectors.toList()); //list 변환
stream.collect(Collectors.joining()); //한개의 string으로 변환
stream.collect(Collectors.joining(", ")); //요소들 사이에 ","을 넣어서 한개의 string 반환

8.간단 예제

  • Stream API를 이용한 간단한 짝수 판별
IntStream.range(1, 11).filter(i-> i%2==0)
      .forEach(System.out::println); //같은 뜻
	  .forEach(i->System.out.println(i)); //같은 뜻

9.간단 예제

  • 0~1000까지의 값 중 500이상이며 짝수이면서 5의 배수인 수의 합을 구하라
System.out.println(
      IntStream.range(0, 1001)
            .skip(500)
            .filter(i-> i%2==0)
            .filter(i-> i%5==0)
            .sum()
);

0개의 댓글