[학습 목표]
1. 스트림 (Stream API)를 활용하여 데이터를 효율적으로 변환, 필터링, 집계 및 병렬 처리를 할 수 있으며, 성능을 최적화할 수 있다. ( java.util -> stream -> 변환 , 필터링 집계 및 병렬 처리) 2. 스트림 중간 연산 (Intermediate Operation)과 최종 연산(Terminal Operations)의 개념을 이해하고, 다양한 연산 ( map , filter, sorted , reduce ,collect 등)을 활용하여 데이터를 효과적으로 처리할 수 있다. 3. 여러 연산 단계를 연결하 스트림 파이프라인의 특성을 이해하고 활용할 수 있다. 4. 컬렉션이나 배열 데이터를 스트림으로 전환하여 선언적 프로그래밍으로 변환 후 프로세싱 할 수 있다. |
Stream API
>> 데이터 집합을 효과적으로 처리할 수 있는 API 필터링, 그룹핑 등 가능
1) Stream 연산 순서
a. 생성 : Collection.stream() , Stream.of() , Arrays.stream() -> 내부적으로 데이터 처리를 쉽게 하겠다는 의미
- java.util의 메소드에도 stream() 이 있다 -> 요소를 기준으로 생성
- java.lang.stream에 Stream에서 of(T...values) 메소드가 있다 -> 값을 기준으로 스트림 생성
- java.util의 Arrays 클래스에 stream(T[] array) 메소드를 볼 수 있다. -> 배열 객체 기준으로 스트림 생성
b. 중간 연산 (Intermediate Operation) -> 중간에 조건 연산
filter(), map(), sorted(), distinct(), limit(), flatMap() 등
중간 연산은 스트림을 변환하는 작업을 수행하며, 최종 연산이 호출될 때 실행된다
c. 최종 연산 (Terminal Operation) -> 집계 결과
forEach(), collect(), reduce(), count(), sum(), min(), max() 등
최종 연산이 수행되면 스트림이 소비되며, 이후에는 다시 사용할 수 없다
2) Stream 주요 연산
(map() 과 reduce()를 합해서 mr 작업이라고 하는데 이는 자주 사용함) {집계 연산할 때 합이 좋음}
>> map() : 요소 변환 -> Stream<R> map(Function<T, R> mapper) -> R apply(T t)
형변환 map(String :: valueOf)
문자열 소대문자 변환 map(String::toUpperCase),
객체에서 String을 추출해서 가져오는 것 map(person -> person.name)
-> Stream<String> stream = IntStream.rangeClosed(1, 10).mapToObj(String::valueOf);
mapToObj -> 객체를 스트림으로 변환
map : 원하는 형으로 바꾸는 것
package com.sec12.mstream;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Stream;
import java.util.stream.IntStream;
public class StreamTest04 {
public static void main(String[] args) {
//Q1. 1~10까지 정수형 값을 스트림 생성 후 출력 map() : 요소 변환 -> 정수를 문자열로 변환 String.valueOf()
//일반 Stream 이 아닌 특정 타입형 IntStream 같은 경우에는 map이 아닌 mapToObj로 객체로 변환하여 리턴해야한다
Stream<String> stream2 = IntStream.rangeClosed(1,10).maptToObj(String::valueof);
StreamTest.printStream("Q1. 1~10까지 정수형 값을 스트림 생성 후 출력 map()", stream);
//Q2. 10 ~1 까지 정수형 값을 스트림 생성 후 출력 -> iterate 방법
Stream <String> stream2 = IntStream.iterate(10,i->i-1).limit(10).mapToObj(String::valueOf);
StreamTest.printStream("Q2. 10 ~1 까지 정수형 값을 스트림 생성 후 출력 ", stream2);
//Q3. 10 ~ 1 까지 정수형 값을 스트림 생성 후 출력 -> rangeClosed 방법
Stream<String> stream3 = IntStream.rangeClosed(1,10) //1 ~ 10까지 정수 스트림
.map(i -> 11 -i) // 역순으로 리턴 하겠다
.mapToObj(String::valueOf); // 문자열 변환 후 스트림 생성 후 리턴
StreamTest.printStream("Q3. 10 ~ 1 까지 정수형 값을 스트림 생성 후 출력 -> rangeClosed 방법", stream3);
//Q4. Stream<Integer> boxed() + sorted(Comparator.reverseOrder()) 사용함
Stream<String> stream4 = IntStream.rangeClosed(1,10)
.boxed() //기본형 int -> Integer
.sorted((a,b) -> b-a) //역순 내림차순
.map(String::valueOf);
StreamTest.printStream("Q4. Stream<Integer> boxed() + sorted(Comparator.reverseOrder()) 사용함",stream4);
}
}
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamTest02 {
public static void main(String[] args) {
//Q1 . 1~10 까지 정수형 값을 스트림 생성 후 출력 map() : 요소 변환 -> 정수를 문자열로 변환 String.valueof()
//int arr[] = {1,2,3,4,5,6,7,8,9,10}; 일반 타입은 안됨 wrapper로 와야 함
Integer arr[] = {1,2,3,4,5,6,7,8,9,10};
//Stream<String> streamFroBalues = Arrays.asList("1","2","3",...."10");
Stream<String> streamFroBalues = Arrays.stream(arr).map(String::valueOf);
StreamTest.printStream("Q1 . 1~10 까지 정수형 값을 스트림 생성 후 출력: ",streamFroBalues);
//Q2 "import java.util.stream.Stream"는 문자열을 잘라서 배열 후 만든 후 스트림 생성 후 룰력
String[] stringArray = "import java.util.stream.Stream".split(" ");
Stream<String> stream2 = Arrays.stream(stringArray);
StreamTest.printStream("Q2 \"import java.util.stream.Stream\"는 문자열을 잘라서 배열 후 만든 후 스트림 생성 후 룰력", stream2);
//Q3. 10 ~1 까지 정수형 값을 스트림 생성 후 출력
Integer[] arr1 = {10,9,8,7,6,5,4,3,2,1};
Stream<String> stream3 = Arrays.stream(arr1).map(String::valueOf);
StreamTest.printStream("Q3. 10 ~1 까지 정수형 값을 스트림 생성 후 출력", stream3);
}
}
>> filter() :조건에 맞는 요소만 선택
List<String> result = Arrays.stream(str.split("\s+"))
.filter(word -> word.length() >= 5)
.map(String::toUpperCase).collect(Collectors.toCollection(ArrayList::new));
System.out.println(result);
>> sorted() : 정렬 수행
>> reduce() : 누적 연산 수행 -> BiFunction<T,U,R> , reduce ((a,b) -> a+b)
package com.sec12.mstream;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class ReduceTest {
public static void main(String[] args) {
// 1️. Optional<T> reduce(BinaryOperator<T> accumulator)
// 리스트의 모든 값을 합산하여 Optional<Integer>로 반환
List<Integer> numbers = Arrays.asList(10, 20, 30, 40, 50);
Optional<Integer> sum = numbers.stream().reduce(Integer::sum);
// Optional 값이 존재하면 출력, 없으면 "noValue" 출력
System.out.println(sum.orElseGet(() -> {
System.out.println("noValue");
return 0;
}));
System.out.println(sum.orElseGet(() -> 0));
// 2. T reduce(T identity, BinaryOperator<T> accumulator)
// 초기값(identity) 0을 지정하여 리스트의 모든 값을 합산
int sum01 = numbers.stream().reduce(0, Integer::sum);
System.out.println("Sum with identity: " + sum01);
// 3. <U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
// 병렬 스트림을 사용하여 초기값 0.0을 지정한 후, BiFunction과 BinaryOperator를 통해 병렬 연산 수행
double sum03 = numbers.parallelStream().reduce(
0.0, // 초기값(identity)
(partialSum, a) -> partialSum + a, // BiFunction<U, ? super T, U>
Double::sum // BinaryOperator<U>
);
System.out.println("Parallel Sum: " + sum03);
}
}
>> collect(): 리스트, 맵 등으로 변환
>>peek() : 변환 작업을 할 때 테스트 용으로 사용
3) 병렬 처리 parallelStream()을 활용하면 데이터 병렬 처리가 가능하다.
package com.sec12.mstream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
//직렬 처리(Sequential Processing)와 병렬 처리(Parallel Processing)를 비교해보자.
public class ParallelTest01 {
public static void main(String[] args) {
// 리스트 초기화
List<BigDecimal> list = createBigDecimalList();
// 직렬 처리 실행
long start = System.currentTimeMillis();
BigDecimal sequentialResult = processSequential(list);
long end = System.currentTimeMillis();
System.out.println("=======> 직렬 처리 시간: " + (end - start) + "ms");
// 병렬 처리 실행
start = System.currentTimeMillis();
BigDecimal parallelResult = processParallel(list);
end = System.currentTimeMillis();
System.out.println("==========> 병렬 처리 시간: " + (end - start) + "ms");
}
/**
* BigDecimal 리스트 생성
*/
private static List<BigDecimal> createBigDecimalList() {
List<BigDecimal> list = new ArrayList<>();
list.add(new BigDecimal("1"));
list.add(new BigDecimal("2"));
list.add(new BigDecimal("3"));
list.add(new BigDecimal("4"));
list.add(new BigDecimal("5"));
return list;
}
/**
* 직렬(Sequential) 스트림 처리
*/
private static BigDecimal processSequential(List<BigDecimal> list) {
System.out.println("--- 직렬 처리 (Sequential Processing) ---");
return list.stream().reduce(new BigDecimal("100"), (value1, value2) -> {
printValues(value1, value2);
return value1.add(value2);
});
}
/**
* 병렬(Parallel) 스트림 처리
*/
private static BigDecimal processParallel(List<BigDecimal> list) {
System.out.println("\n--- 병렬 처리 (Parallel Processing) ---");
return list.parallelStream().reduce(new BigDecimal("100"), (value1, value2) -> {
printValues(value1, value2);
return value1.add(value2);
});
}
/**
* 연산 과정 출력
*/
private static void printValues(BigDecimal value1, BigDecimal value2) {
System.out.println("value1 = " + value1);
System.out.println("value2 = " + value2);
}
}
'🦁멋쟁이 사자처럼 15기 > 3월달 수업 내용 정리' 카테고리의 다른 글
멋쟁이 사자처럼 15회차 ( 03 / 19 ) (0) | 2025.03.19 |
---|---|
멋쟁이 사자처럼 14회차 ( 03 / 18 ) (0) | 2025.03.18 |
멋쟁이 사자처럼 12회차 ( 03 / 14 ) (0) | 2025.03.14 |
멋쟁이 사자처럼 12회 ( 03 / 13 ) (0) | 2025.03.13 |
멋쟁이 사자처럼 11회차 ( 03 / 12 ) (0) | 2025.03.12 |