Stream이란
Java8부터 지원하는 Stream은 다양한 데이터 소스(컬렉션, 배열 등)의 요소들을 하나씩 참조하며 반복적인 처리를 가능케 하여 표준화된 방법으로 다룰 수 있게 해준다. 이러한 Stream을 이용한다면 불필요한 for문과 그 안에서 이루어지는 if문등의 분기 처리를 쓰지 않고도 깔끔하고 직관적인 코드로 변형할 수 있다.
Stream의 특징
- Stream은 원본데이터로부터 데이터를 읽기만 할 뿐, 원본 데이터 자체를 변경하지 않는다.
- Stream은 일회용이며 한 번 사용하면 닫혀서 재사용이 불가능하다. 필요하다면 정렬된 결과를 컬렉션이나 배열에 담아 반환할 수 있다.
- Stream은 최종 연산 전까지 중간연산이 수행되지 않는 지연된 연산을 수행한다.
- Stream은 작업을 내부 반복으로 처리한다.
Stream의 구조
1. Stream 생성
2. 중개연산 : 연산 결과가 스트림인 연산 (0 ~ n번 사용 가능)
3. 최종연산 : 연산결과가 스트림이 아닌 연산 (0~ 1번 사용 가능)
Stream 생성
- Collection인터페이스의 stream()으로 Stream생성
List<Integer> list = Arrays.asList(1,2,3,4,5);
Stream<Integer> intStream = list.stream();
intStream.forEach(System.out::print) //1 2 3 4 5
- 배열로 Stream 생성
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 = Arrays.stream(new int[]{1,2,3,4,5});
Stream<Integer> integerStream = Arrays.stream(new Integer[]{1,2,3,4,5});
//기본형 Stream이며 더 많은 기능을 사용할 수 있음
System.out.println(intStream.sum());
System.out.println(intStream.count());
System.out.println(intStream.average());
- 난수 Stream 생성
IntStream intStream = new Random().ints(); //출력할 시 중간연산자limit으로 잘라줘야됨
IntStream intStream = new Random().ints(5); //5개의 난수 생성
IntStream intStream = new Random().ints(5, 1, 10); //1~10 사이의 5개의 난수 생성
- 람다식으로 Stream 생성
//iterate()는 초기값과 이전 요소를 사용해서 다음 요소를 계산한다.
//iterate(초깃값(이전요소), 람다식(UnaryOperator))
Stream<Integer> intStream = Stream.iterate(0, n -> n + 2);
intStream.limit(5).forEach(System.out::println); //0, 2, 4, 6, 8
//generate()는 초기값과 이전요소를 사용하지 않는다.
//generate(람다식(Supplier))
Stream<Integer> oneStream = Stream.generate(() -> 1);
oneStream.limit(5).forEach(System.out::print); // 1, 1, 1, 1, 1
- 파일로 Stream 생성
//path로 지정된 경로의 폴더의 파일을 Stream으로 변환해줌
Stream<Path> Files.list(Path dir)
//path로 지정된 경로의 파일의 내용을 줄단위로 읽어서 Stream으로 변환해줌
Stream<String> Files.lines(Path path)
중간연산
- skip(long n) : 앞에서부터 n개 건너뛰기
IntStream intStream = IntStream.rangeClosed(1, 10); //1,2,3,4,5,6,7,8,9,10
intStream.skip(3).forEach(System.out::print); //4,5,6,7,8,9,10
- limit(long maxSize) : maxSize 이후의 요소는 잘라냄
IntStream intStream = IntStream.rangeClosed(1, 10); //1,2,3,4,5,6,7,8,9,10
intStream.limit(5).forEach(System.out::print); //1,2,3,4,5
- filter(조건식) : 조건식에 맞지 않는 요소 제거
IntStream intStream = IntStream.rangeClosed(1, 10); //1,2,3,4,5,6,7,8,9,10
intStream.filter(i->i%2==0).forEach(System.out::print); //2,4,6,8,10
- distinct() : 중복제거
IntStream intStream = IntStream.of(1, 2, 3, 3, 4, 5, 5, 6, 7);
intStream.distinct().forEach(System.out::print); //1, 2, 3, 4, 5 ,6, 7
- sorted() : 스트림 요소를 기본 정렬
//기본정렬
Stream<String> strStream = Arrays.stream(new String[]{"a","a","a","b","c","c","C","C","d","d"});
strStream.sorted().forEach(System.out::print);; //CCaaabccdd
//기본정렬의 역순
Stream<String> strStream = Arrays.stream(new String[]{"a","a","a","b","c","c","C","C","d","d"});
strStream.sorted(Comparator.reverseOrder()).forEach(System.out::print);; //ddccbaaaCC
//기본정렬(대소문자 구분 없음)
Stream<String> strStream = Arrays.stream(new String[]{"a","a","a","b","c","c","C","C","d","d"});
strStream.sorted(String.CASE_INSENSITIVE_ORDER).forEach(System.out::print); //aaabccCCdd
- map() : 스트림의 요소 변화하기
Stream<File> fileStream = Arrays.stream(new File[]{new File("Ex1.java"),new File("Ex2.java"),new File("Ex3.txt"),new File("Ex4.bak")});
fileStream.map(File::getName) //Stream<File>을 Stream<String>으로 변환
.map(s -> s.substring(s.indexOf('.')+1)) //확장자만 추출
.map(String::toUpperCase) //확장자를 대문자로 변환
.distinct() //중복제거
.forEach(System.out::print);
- flatMap() : 스트림의 스트림을 스트림으로 변환
Stream<String[]> strArrStream = Stream.of(new String[]{"abc","def","ghi"}, new String[]{"jkl","mno","pqr"});
strArrStream
.flatMap(Arrays::stream)
.forEach(System.out::print); //abcdefghijklmnopqr
//일반적으로 String[] 배열을 Stream으로 변환 하게 되면 Stream<Stream<String>>형태로 변환된다.
/*
strArrStream
.map(Arrays::stream)
.forEach(System.out::print);
출력:java.util.stream.ReferencePipeline$Head@b684286java.util.stream.ReferencePipeline$Head@880ec60
*/
최종연산
- forEach(), forEachOrdered() : 스트림의 모든 요소에 지정된 수업을 수행
//직렬스트림
IntStream.range(1, 10).forEach(System.out::print); //123456789
//병렬스트림(병렬스레드로 처리하기 때문에 순서보장이 안됨)
IntStream.range(1, 10).parallel().forEach(System.out::print); //657891423
//병렬스트림인 경우 forEachOrdered를 사용하면 순서 보장이 됨
IntStream.range(1, 10).parallel().forEachOrdered(System.out::print);
- allMatch(), anyMatch(), noneMatch() : 조건 검사
//배열의 모든 숫자가 10이하 이면 true
boolean b = Arrays.stream(new int[]{1,6,9,10,8}).allMatch(i -> i <= 10);
System.out.println(b);
//배열의 모든 숫자 중에 10보다 큰 숫자가 있으면 true
boolean b2 = Arrays.stream(new int[]{1,6,9,10,8}).anyMatch(i -> i > 10);
System.out.println(b2);
//배열의 모든 숫자 중에 10보다 큰 숫자가 없으면 true
boolean b3 = Arrays.stream(new int[]{1,6,9,10,8}).noneMatch(i -> i > 10);
System.out.println(b3);
//배열의 모든 숫자 중에 5보다 큰 첫번째 숫자
Optional<Integer> result = Arrays.stream(new Integer[]{1,6,9,10,8}).filter(i -> i > 5).findFirst();
System.out.println(result.get()); //6
//배열의 모든 숫자 중에 5보다 큰 첫번째 숫자(병렬 처리이기 때문에 순서 보장이 안됨)
Optional<Integer> result2 = Arrays.stream(new Integer[]{1,6,9,10,8}).filter(i -> i > 5).findAny();
System.out.println(result2.get()); //6
- reduce() : 스트림의 요소를 하나씩 줄여가며 누적 연산 수행
//reduce(int identity, IntBinaryOperator op)
//reduce(초깃값, 작업할 수행)
//reduce(작업할 수행)과 같이 초깃값을 주지 않으면 null이 반환 될 수 도있기 때문에 Optional<Integer>로 반환이 된다
//배열의 요소가 몇개있는지
int cnt = Arrays.stream(new Integer[]{1,6,9,10,8}).reduce(0, (a,b) -> a + 1);
System.out.println(cnt); //5
/*
int cnt = 0;
for(int a : new int[]{1,6,9,10,8}) {
cnt += 1;
}
System.out.println(cnt);
*/
//배열의 모든 요소의 합
int sum = Arrays.stream(new Integer[]{1,6,9,10,8}).reduce(0, (a,b) -> a + b);
System.out.println(sum);
/*
int sum = 0;
for(int a : new int[]{1,6,9,10,8}) {
sum += a;
}
System.out.println(sum);
*/
//배열의 모든 요소 중 제일 큰 값
int max = Arrays.stream(new Integer[]{1,6,9,10,8}).reduce(Integer.MIN_VALUE, (a,b) -> a > b ? a : b);
System.out.println(max);
//배열의 모든 요소 중 제일 작은 값
int min = Arrays.stream(new Integer[]{1,6,9,10,8}).reduce(Integer.MAX_VALUE, (a,b) -> a < b ? a : b);
System.out.println(min);
'JAVA' 카테고리의 다른 글
String.valueOf() 와 Integer.toString() 의 차이 (0) | 2024.05.01 |
---|---|
String, StringBuffer, StringBuilder의 차이점 (0) | 2024.04.24 |
람다식(Lambda Expression) (0) | 2022.07.17 |
enum (0) | 2022.01.16 |
JAVA 실행과정 & JVM (0) | 2022.01.09 |