14-15~16 스트림, 스트림의 특징

19505 단어 JavaJava
  • CF(컬렉션 프레임워크) : List, Set, Map 사용방법이 달라서 사실상 표준화 실패(반쪽짜리 표준화)

스트림(Stream)

  • 다양한 데이터 소스(컬렉션, 배열)를 표준화된 방법으로 다루기 위한 것(JDK 1.8)
  • 스트림 생성 방법
Stream<T> Collection stream()

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

// 컬렉션
Stream<Integer> intStream = list.stream();

// 배열
Stream<String> strStream = Stream.of(new String[]{"a", "b", "c"});

// 람다식
Stream<Integer> evenStream = Stream.iterate(0, n -> n + 2); // 0, 2, 4, 6, ...
Stream<Double> randomStream = Stream.generate(Math::random);

// 난수 스트림(크기가 5)
IntStream intStream = new Random().ints(5);	
  • 데이터 소스 -> Stream -> 중간 연산(n번) -> 최종 연산(1번) -> 결과
  1. 스트림 만들기
  2. 중간 연산(0 ~ n번)
  3. 최종 연산(0 ~ 1번)

스트림이 제공하는 기능 - 중간 연산, 최종 연산

  • 중간 연산 : 연산 결과가 스트림인 연산. 반복적으로 적용 가능
  • 최종 연산 : 연산 결과가 스트림이 아닌 연산. 단 한 번만 적용 가능(스트림의 요소를 소모)
String[] strArr = {"dd", "aaa", "CC", "cc", "b"};

// 1. 문자열 배열이 소스인 스트림 생성
Stream<String> stream = Stream.of(strArr);

// 2. 중간 연산
Stream<String> filteredStream = stream.filter(); // 걸러내기
Stream<String> distinctedStream = stream.distinct(); // 중복 제거
Stream<String> sortedStream = stream.sort();	// 정렬
Stream<String> limitedStream = stream.limit(5);	// 스트림 자르기

// 3. 최종 연산
int total = stream.count();	// 요소 개수 세기

스트림의 특징

  • 스트림은 데이터 소스로부터 데이터를 읽기만할 뿐(ReadOnly) 변경하지 않는다.
List<Integer> list = Arrays.asList(3, 1, 5, 4, 2);
List<Integer> sortedList = list.stream().sorted()  // list를 정렬해서
		.collect(Collectors.toList()); // 새로운 List에 저장
System.out.println(list);	// [3, 1, 5, 4, 2]
System.out.println(sortedList); // [1, 2, 3, 4, 5]
  • 스트림은 Iterator처럼 일회용이다.(필요하면 다시 스트림을 생성해야 함)
strStream.forEach(System.out::println);	// 모든 요소를 화면에 출력(최종 연산)
int numOfStr = strStream.count();	// 에러. 스트림이 이미 닫혔음
  • 최종 연산전까지 중간 연산이 수행되지 않는다. - 지연된 연산
// 코드만 보면 말이 안되는 것 같지만 지연된 연산때문에 가능하다.
IntStream intStream = new Random().ints(1, 46); // 1~45 범위의 무한 스트림
intStream.distinct().limit(6).sorted()		  // 중간 연산
	.forEach(i -> System.out.print(i + ",")); // 최종 연산
  • 스트림은 작업을 내부 반복으로 처리한다.
for(String str : strList)
	System.out.println(str);
- 위 코드를 아래와 같이 쓸 수 있다.
stream.forEach(System.out::println);
- 다음과 같이 정의되어 있기 때문이다.
void forEach(Consumer<? super T> action){
    Objects.requireNonNull(action);	// 매개변수의 널 체크
    
    for(T t : src)	// 내부 반복(for문을 메서드 안으로 넣음)
    	action.accept(T);
}
  • 병렬 스트림 지원: 스트림의 작업을 병렬로 처리, 멀티 쓰레드로 병렬처리(빅데이터 처리)
Stream<String> strStream.of("dd", "aaa", "CC", "cc", "b");
int sum = strStream.parallel() // 병렬 스트림으로 전환(속성만 변경)
	.mapToInt(s -> s.length()).sum(); // 모든 문자열의 길이의 합
  • 성능 개선을 하고 싶을 때(빅데이터 처리) : 기본형 스트림 - IntStream, LongStream, DoubleStream 사용
    - 오토박싱 & 언박싱의 비효율이 제거됨(Stream 대신 IntStream 사용)
    - 숫자와 관련된 유용한 메서드를 Stream<'T'>보다 더 많이 제공

좋은 웹페이지 즐겨찾기