[Java] Stream 스트림_1

김동욱·2023년 9월 15일
0

Java

목록 보기
8/8
post-thumbnail

다음 내용은 남궁성의 정석코딩 스트림편 을 보며 참고하여 정리한 내용입니다.

스트림

다양한 데이터 소스를 표준화된 방법으로 다루기 위한 것입니다.

배열이나 컬렉션 프레임워크 List, set, map로부터 straem을 만들어서 같은 방식으로 작업

List<Integer> list = Arrays.asList(1,2,3,4,5);
Stream<Integer> intStream = list.stream();
Stream<String> strStream = Stream.of(new String[]{'a','b'};
Stream<Integer> evenStream = Stream.iterate(0, n -> n+2)
Stream<Integer> ramdomStream = Stream.generate(Math::ramdom);
IntStream intStream = new Ramdom().ints(5);

스트림 연산 과정 : 스트림 생성 → 중간작업 (0~n번) → 최종작업(0~1번)

데이터의 연속적인 흐름으로 만들어서 한개 한개씩 중간 작업해주고 최종작업을 합니다.

중간 연산 : 연산 결과가 스트림인 연산, 반복적으로 적용 가능

최종연산 : 연산 결과가 스트림이 아닌 연산, 단 한번만 적용 가능(스트림의 요소를 소모)

ex)
stream.distinct().limit(5).sorted().forEach(System.out::println)
                       중간연산  <- -> 최종

스트림의 특징

  1. 데이터 소스로부터 데이터를 읽기만 할 뿐 변경하지 않는다.
List<Integer> list = Arrays.asList(4,1,2,3);
List<Integer> sortlist = list.stream().sorted()
													.collect(Collectors.toList);
sout(list); // 4,1,2,3
sout(sortList); // 1,2,3,
  1. 스트림은 iterator 처럼 일회용이다. (필요하면 다시 스트림을 생성해야함)
strStream.forEach(System.out::println); //모든 요소를 출력(최종연산)
int numOfStr = strStream.count(); //에러
  1. 최종 연산 전까지 중간 연산이 수행되지 않는다 - 지연된 연산
IntStream intStream = new Ramdom().ints(1,46)
IntStream.distinct().limit(6).sorted()
.forEach(i -> sout(i+",")
  1. 반복을 내부 반복으로 처리한다.
  2. 작업을 병렬로 처리 - 병렬스트림(멀티 쓰레드)
Stream<String> strStream = Stream.of("dd","aaa")
int sum  = strStream.parallel() //병렬 스트림으로 전환(속성만 변경)
					.mapToInt(s -> s.length()).sum; //모든 문자열 길이의 합
  1. 기본형 스트림 - ( IntStream, LongStream, DoubleStream)

{1,2,3} 같은 기본형 데이터를 스트림에 저장하려면

1 → new Integer(1) 처럼 기본형을 참조형으로 변환하여 저장하게 되고 이를 오토박싱이라고 한다.

참조형으로 저장한 1을 다시 연산에 사용하려면 다시 1로 변환하는 과정이 필요한데 이를 언박싱이라고 하며 기본형 스트림은 오토박싱, 언박싱의 비효율을 제거해준다.

  • Stream 대신 IntStream을 써준다.
  • 숫자와 관련된 유용한 메서드를 Stream 보다 더 많이 제공한다.
    • T에 숫자가 들어올지, 다른 형식이 들어올지 모르기 때문

스트림 만들기

  1. 컬렉션으로부터 스트림 만들기
List<Integer> list = Arrays.asList(1,2,3,4,5);
Stream<Integer> intStream = list.stream(); // list를 스트림으로 변환

// 스트림의 모든 요소를 출력
intStream.forEach(System.out::print) // 12345
intStream.forEach(System.out::print) // 이미 닫힌 스트림
  1. 객체 배열로부터 스트림 생성하기
Stream<T> Stream.of(T...values)
Stream<T> Stream.of(T[])
Stream<T> Arrays.stream(T[])

// 기본형 배열로부터 스트림 생성
IntStream IntStrem.of(int...values)
IntStream IntStrem(int[])
  1. 임의의 수로부터 스트림 만들기
IntStream intStream = new Random().ints(); //무한 스트림 
intStream.limit(5).forEach(System.out::println); //리미트가 없으면 무한대로 출력

IntStream intStream = new Ramdom().ints(5); // 지정된 범위의 난수
  1. 특정 범위의 정수로 스트림 만들기
Intstream intStream = IntStream.range(int begin, int end);
  1. 람다식으로 스트림 만들기
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f) // 이전 요소에 종속적
static <T> Stream<T> generate(Supplier<T> s) // 이전 요소에 독립적

iterate()는 이전 요소를 seed로 해서 다음 요소를 계산한다.

Stream<Integer> evenStream = Stream.iterate(0, n → n+2)

generate()는 seed를 사용하지 않는다.

Stream<Double> randomStream = Stream.generate(Math::random)
Stream<Integer> oneStream = Stream.generate(()->1);

스트림 연산

  • 중간 연산

연산 결과가 스트림인 연산, 즉 중간 연산을 거쳐도 여전히 스트림인 상태

중간연산설명
Stream distinct()중복을 제거
Stream filter(Predicate predicate)조건에 안 맞는 요소 제외( 맞는 것만 남겨둠)
Stream skip(long n)일부를 잘라냄
Stream peek(Consumer action)요소에 작업 수행 (중간에 처리 결과 확인)

| Stream sorted()
Stream sorted(Comparator comparator) | 요소를 정렬 |
| Stream map(Function<T,R> mapper
DoubleStream mapToDouble(ToDoubleFunction mapper
IntStream mapToInt(ToIntFunction mapper
LongStream mapToLong(ToLongFunction mapper | 요소를 변환한다. |
| Stream flatMap(Function<T,Stream> mapper>
DoubleStream flatMapToDouble(Function<T, DoubleStream>m)
IntStream flatMapToInt(Function<T, IntStream> m)
LongStream flatMapToLong(Function<T, LongStream> m) | 요소를 변환한다. |

map() : 요소 변환

flatmap() : 스트림의 스트림 → 스트림으로

profile
안녕하세요. 공부해요

0개의 댓글