- 스트림(Stream) API은 람다식(Lambda Expression)를 이용한 기술 중에 하나로 데이터 소스(컬렉션, 배열, 난수, 파일 등…)를 조작 및 가공, 변환하여 원하는 값으로 반환해주는 인터페이스를 의미합니다.
- 해당 기능을 사용하기 위해서는 Java 1.8 이상의 버전을 사용해야 합니다.
- 해당 스트림 인터페이스는 import java.util.stream 에 포함되어 있습니다.
- 스트림은 외부 반복을 통해 작업하는 컬렉션과는 달리 내부 반복(Internal iteration)을 통해 작업을 수행합니다.
- 스트림은 재사용이 가능한 컬렉션과는 달리 단 한번만 사용할 수 있습니다.
- 스트림은 원본 데이터를 변경하지 않습니다.
- 스트림의 연산은 필터-맵(filter-map) 기반의 API를 사용하여 지연(lazy) 연산을 통해 성능을 최적화합니다.
- 스트림이 제공하는 다양한 연산을 이용해 복잡한 작업들을 간단히 처리 가능
- 스트림에 제공하는 연산은
중간연산과최종 연산으로 분류
최종 연산 : 연산 결과가 스트림이 아닌 연산. 스트림의 요소를 소모하므로 단 한번만 가능하다.


Stream<String> strStream = Stream.of("a", "b", "c"); // 가변인자
Stream<String> strStream = Stream.of(new String[]{"a", "b", "c"});
Stream<String> strStream = Arrays.stream(new String[]{"a", "b", "c"});
Stream<String> strStream = Arrays.stream(new String[]{"a", "b", "c"}, 0, 3);
IntStream intStream = IntStream.range(1, 5); // 1,2,3,4
IntStream intStream = IntStream.rangeClosed(1, 5); // 1,2,3,4,5
List<String> list = Arrays.asList("a","b","c");
Stream<String> stream = list.stream();
Stream<String> generatedStream = Stream.generate(()->"a").limit(3);
// 생성할 때 스트림의 크기가 정해져있지 않기(무한하기)때문에 최대 크기를 제한해줘야 한다.
Stream<Integer> iteratedStream = Stream.iterate(0, n->n+2).limit(5); //0,2,4,6,8
스트림 자르기 - skip()-앞에서부터 n개 skip하기,limit()-최대 크기 제한스트림 요소 걸러내기 - filter(), distinct() //filter
IntStream test1 = IntStream.rangeClosed(1, 10); // 1 ~ 10 숫자
test1.filter(i -> i%2==0).forEach(System.out::print);
//distinct
IntStream test2 = IntStream.of(1, 2, 3, 3, 2, 5, 7, 6, 9);
test2.distinct().forEach(System.out::print);
정렬 Stream<String> strStream = Stream.of("b", "cc", "D", "C", "AA", "F");
/* 오름차순 기본 정렬 */
// AA, C, D, F, b, cc
strStream.sorted(); // 기본 정렬
strStream.sorted((s1,s2)-> s1.compareTo(s2)); // 람다식
strStream.sorted(String::compareTo); // 위 문장과 같다.
/* 내림차순 역순 정렬 */
// cc, b, F, D, C, AA
strStream.sorted(Comparator.reverseOrder()); // 기본 정렬 역순
strStream.sorted((s1,s2)-> s2.compareTo(s1)); // 람다식
/* 대소문자 구분 없는 오름차순 정렬 */
// AA, b, C, cc, D, F
strStream.sorted(String.CASE_INSENSITIVE_ORDER);
/* 대소문자 구분없는 내림차순 정렬 */
// F, D, cc, C, b, AA
strStream.sorted(String.CASE_INSENSITIVE_ORDER.reversed());
/* 길이 순 오름차순 정렬 */
// b, D, C, F, cc, AA
// !! 만약 정렬 조건을 추가한다면 .thenComparing()을 붙여 정렬조건을 추가할 수 있습니다.
strStream.sorted(Comparator.comparing(String::length));
strStream.sorted(Comparator.comparingInt(String::length)); // no 오토박싱
/* 길이 순 내림차순 정렬 */
// cc, AA, b, D, C, F
strStream.sorted(Comparator.comparing(String::length).reversed());
Stream<String> stream = list.stream()
.map(String::toUpperCase);
//[A,B,C]
.map(Integers::parseInt);
// 문자열 -> 정수로 변환
IntStream stream = list.stream()
.count() //스트림 요소 개수 반환
.sum() //스트림 요소의 합 반환
.min() //스트림의 최소값 반환
.max() //스트림의 최대값 반환
.average() //스트림의 평균값 반환
IntStream stream = IntStream.range(1,5);
.reduce(10, (total,num)->total+num);
//reduce(초기값, (누적 변수,요소)->수행문)
// 10 + 1+2+3+4+5 = 25
members.stream()
.map(Person::getName)
.forEach(System.out::println);
//결과를 출력 (peek는 중간, forEach는 최종)
Person person = members.stream()
.findAny() //먼저 찾은 요소 하나 반환, 병렬 스트림의 경우 첫번째 요소가 보장되지 않음
.findFirst() //첫번째 요소 반환
https://velog.io/@yun8565/Java-%EC%8A%A4%ED%8A%B8%EB%A6%BCStream-%EC%A0%95%EB%A6%AC
https://hstory0208.tistory.com/entry/Java%EC%9E%90%EB%B0%94-Stream%EC%8A%A4%ED%8A%B8%EB%A6%BC%EC%9D%B4%EB%9E%80