
기존엔 컬렉션이나 배열에 데이터를 담고 원하는 데이터를 얻기 위해 for문 이나 Iterator 이용
또한 데이터 소스마다 다른 방식(List -> Collections.sort() , Array -> Arrays.sort())
이런 문제를 해결하기 위해 Stream 사용 (컬렉션(List,Map,Set) 이나 배열에 만들수 있다)
-> Stream 만들면 똑같은 방법으로 작업을 처리한다!
데이터 소스를 추상화(데이터 소스가 무엇이든 간에 같은 방법으로 다룸)
데이터를 다루는데 자주 사용되는 메서드들을 정의
List<Integer> list = Arrays.asList(1,2,3,4,5);
// 스트림 생성
// Collection에 stream() 메서드 호출
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); // 람다식
IntStream intStream = new Random.ints(5); // 난수스트림 (크키가 5)
// 중간 연산 3번, 최종 연산 1번
stream.distinct().limit(5),sorted().forEach(System.in::println)
String[] strArr = {"dd", "aaa", "CC", "cc", "b" };
Stream<String> stream = Stream.of(strArr) // 문자열 배열이 소스인 스트림
Stream<String> filteredStream = stream.filter(); // 걸러내기(중간 연산)
Stream<String> distinctedStream = stream.distinct(); // 중복제거( 중간 연산)
Stream<String> sortedStream = stream.sort(); // 정렬(중간 연산)
Stream<String> limitedStream = stream.limit(5) // 스트림 자르기(중간 연산)
int total = stream.count(); // 최종 연산
List<Integer> list = Arrays.asList(3,1,5,4,2);
// 리스트를 정렬 해서 새로운 리스트에 저장
List<Integer> sortedList = list.stream().sorted()
.collect(Collectors.toList());
System.out.println(list); // [3,1,5,4,2]
System.out.println(sortedList); // [1,2,3,4,5]
일회용이다(필요하면 다시 스트림을 생성해야 함)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 + ",")); // 최종 연산

병렬스트림즉 멀티쓰레드로 처리
// 병렬로 안할려면 sequential() : 기본 -> parallel()호출 취소 시에만 사용
// 큰 작업 빠르게 처리하게 할시 사용!
Stream<String> strSTream = Stream.of("dd", "aaa", "CC", "cc", "b") ;
int sum = strStream.parallel() // 병렬 스트림으로 전환(속성만 변경) -> 새로운 스트림 생성 X
.mapToInt(s -> s.length()).sum(); // 모든 문자열의 길이의 합
Collection인터페이스의 stream() 메서드로 컬렉션을 스트림으로 변환
-> List,set등에서 사용 가능하다
Stream<E> stream()
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); // 에러, 스트림이 이미 닫힘
Stream<T> Stream.of(T...values) // 가변 인자
Stream<T> Stream.of(T[])
Stream<T> Arrays.stream(T[])
// 일부분으로 스트림 만들기
Stream<T> Arrays.stream(T[] array, int startInclusive, int endExclusive)
// LongStream, DoubleStream 들도 존재
IntStream IntSTream.of(int.. values)
IntStream IntSTream.of(int[])
IntStream Arrays.stream(int[])
IntStream Arrays.stream(int[] array, int startInclusive, int endExclusive)
IntStream은 숫자인지 알기에 count()외에도 sum,average 같은 기능 제공
Stream< Integer > 즉 Stream< T >는 숫자외에도 여러 타입의 스트림이 가능해야하므로 숫자 스트림에만 사용할 수 있는 sum(), average()를 넣지 않은 것!
Integer.MIN_VALUE <= ints() <= Integer.MAX_VALUE
Long.MIN_VALUE <= longs() <= Long.MAX_VALUE
0.0 <= doubles() < 1.0
//무한 스트림 생성
IntStream ints(int begin, int end)
LongStream longs(long begin, long end)
DoubleStream doubles(double begin, double end)
// 유한 스트림 생성
IntStream ints(long StreamSize, int begin, int end)
LongStream longs(long StreamSize, long begin, long end)
DoubleStream doubles(long StreamSize, double begin, double end)
IntStream intStream = new Random().ints(); // 무한 스트림
intStream.limit(5).forEach(System.out::println); // 5개 요소 출력
IntStream intStream = new Random().ints(5) // 크기가 5인 난수 스트림 반환
IntStream IntStream.range(int begin, int end)
// 끝 범위 포함
IntStream IntStream.rangeClosed(int begin, int end)
// 이전 요소의 종속적 , seed -> 초기 값
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
// 이전 요소에 독립적
static <T> Stream<T> generate(Supplier<T> s)
Stream<Integer> evenStream = Stream.iterate(0, n-> n+2); // 0,2,4,6 ...
// generate 는 seed 사용 X
Stream<Double> randomStream = Stream.generate(Math::random);
// 기본형 스트림 타입의 참조변수로 다룰 수 없다
// 굳이 바꾸겠다면 mapToInt 메서드로 변환하자
IntStream evenStream = Stream.iterate(0,n->n+2); //에러
Stream<Path> Files.list(Path dir) // Path 파일 또는 디렉토리
// 파일 단위 라인 단위로 읽기
Stream<String> Files.lines(Path path)
Stream<String> Files.lines(Path path, Charset cs)
Stream<String> lines()
중간 연산 종류

최종 연산 종류

스트림의 일부를 잘라낼 때 사용
Stream<T> skip(long n) // 앞에서 부터 n개 건너뛰기
Stream<T> limit(long maxSize) //Maxsize 이후의 요소는 잘라냄
IntStream intSteram = IntStream.rangeClosed(1,10); // 1~10 요소를 가진 스트림
intStream.skip(3).limit(5).forEach(System.out::print); // 45678
스트림의 요소 제거 할 때 사용
Stream<T> filter(Predicate<? super T> predicate) // 조건의 맞지 않는 요소 제거
Stream<T> distinct() // 중복 요소 제거
IntStream intStream = IntStream.of(1,2,2,3,3,3,4,5,5,6);
intStream.distinct().forEach(System.out::print); //123456
IntStream intStream = IntStream.rangeClosed(1,10); // 1~10
intStream.filter(i->i%2==0).forEach(System.out::print); // 246810
스트림 정렬 시 사용
Stream<T> sorted()
Stream<T> sorted(Comparator<? super T> comparator)
Comparator의 comparing()으로 정렬 기준을 제공
// 반환 타입이 comparator여서 반환된 Comparator.comparing을 sorted의 인자로 사용
comparing(Function<T, U> keyExtractor)
comparing(Function<T, U> keyExtractor, Comparator<U> keyComparator)
// 반을 기준으로 정렬할 시
// () -> s.getBan();
studentStream.sorted(Comparator.comparing(Student::getBan)
.forEach(System.out::println);
추가 정렬 기준을 제공할때는 thenComparing 사용
스트림의 요소에 저장된 값 중에서 원하는 필드만 뽑아내거나 특정 형태로 변환해야 할 때
// 매개변수로 T타입을 R타입으로 변환하는 함수를 지정
Stream<R> map<Function<? super T, ? extends R> mapper)
Stream<File> fileStream = Stream.of(new File("Ex1.java"), new File("Ex1")
new File("Ex1.bak"), new File("Ex2.java"), new File("Ex1.txt"));
// 스트림의 모든 파일의 이름을 출력
// getName을 통해 문자열 얻음. file -> String
Stream<String> filenameStream = fileStream.map(File::getName);
filenameStream.forEach(System.out :: println);
// 파일 확장자를 중복 없이 대문자로 뽑아내기
fileStream.map (File::getName)
.filter(s->s.indexOf('.') != -1)
// 확장자 이름 뽑아내기
.map(s->s.substring(s.indexOf('.'+1))
.map(String::toUpperCase)
.distinct()
.forEach(System.out::print); // JAVABAKTXT
스트림의 요소를 소비하지 않고 엿보기 -> 디버깅시 자주 사용
Stream<T> peek(Consumer <? super T> action) // 중간연산
void forEach(Consumer<? super T> action) // 최종연산
fileStream.map(File::getName)
.filter(s-> s.indexOf(".")!= -1)
.peek(s->System.out.printf("filename=%s%n", s))
.map(s-> s.substring(s.indexOf('.')+1))
.peek(s->System.out.printf("extension=%s%n", s))
.forEach(System.out::println);
스트림의 스트림을 스트림으로 변환
// String 배열 담는 스트림
Stream<String []> strArrStrm = Stream.of(new String[] { "abc", "def", "ghi"},
new String[]{"ABC", "GHI", "JKLMN"});
//Stream의 Stream, map을 사용시
//(arr) -> Arrays.stream() // stream은 스태틱 메서드
Stream<Stream<String>> strStrStrm = strArrStrm.map(Arrays::stream)

// 문자열의 배열의 스트림을 문자열 스트림으로 변환
Stream<String> strStrStrm = strArrStrm.flatMap(Arrays::stream);

package ch14;
import java.util.*;
import java.util.stream.*;
public class Ex14_7 {
public static void main(String[] args) {
Stream<String []> strArrStrm = Stream.of(
new String[] { "abc", "def", "jkl"},
new String[] {"ABC", "GHI", "JKL"}
);
Stream<String> strStrm = strArrStrm.flatMap(Arrays::stream);
strStrm.map(String::toLowerCase)
.distinct()
.sorted()
.forEach(System.out::println);
System.out.println();
String[] lineArr = {
"Believe or not It is true",
"Do or do not There is no try",
};
Stream<String> lineStream = Arrays.stream(lineArr);
// + 정규식 -> 하나 이상의공백.
lineStream.flatMap(line -> Stream.of(line.split(" +")))
.map(String::toLowerCase)
.distinct()
.sorted()
.forEach(System.out::println);
System.out.println();
}
}