스트림의 연산
스트림이 제공하는 기능은 ? 중간 연산과 최종 연산이 있다.
중간 연산 : 연산결과가 스트림인 연산. 반복적으로 적용가능
최종 연산 : 연산결과가 스트림이 아닌 연산. 단 한번만 적용가능 (스트림의 요소를 소모)
중간 연산
Stream<T> distinct() - 중복을 제거
Stream<T> filter(Predicate<T> predicate) - 조건에 안 맞는 요소 제외
Stream<T> limit(long maxSize) - 스트림의 일부를 잘라낸다
Stream<T> skip(long n) - 스트림의 일부를 건너 뛴다
Stream<T> peek(Consumer<T> action) - 스트림의 요소에 작업수행
Stream<T> sorted()
Stream<T> sorted(Comparator<T> comparator) 스트림의 요소를 정렬한다.
스트림의 요소를 변환
Stream<R> map(Function<T,R> mapper)
DoubleStream mapToDouble(ToDoubleFunction<T> mapper)
IntStream mapToInt(ToIntFunction<T> mapper)
LongStream mapToLong(ToLongFunction<T> mapper)
Stream<R> flatMap(Function<T,Stream<R>> mapper)
DoubleStream flatMapToDouble(Function<T.DoubleStream> m)
IntStream flatMapToInt(Function<T, IntStream> m)
LongStream flatMapToLong(Function<T,LongStream> m)
최종 연산
void forEach(Consumer<? super T> action>
void forEachOrdered(Consumer<? super T>action) - 각 요소에 지정된 작업 수행
(Ordered 붙으면 순서 유지됨, 병렬 스트림이여도)
long count() - 스트림의 요소의 개수 반환
Optional<T> max (Comparator<? super T> comparator)
Optional<T> min (Comparator<? super T> comparator)
스트림의 최대값/최소값을 반환
스트림의 요소 하나를 반환
Optional<T> findAny() //아무거나 하나
Optional<T> findFirst() //첫번째 요소
주어진 조건을 모든 요소가 만족시키는지, 만족시키지 않는지 확인
boolean allMatch(Predicate<T> p) // 모두 만족 하는지
boolean anyMatch(PredicaAte<T> p ) // 하나라도 만족하는지
boolean nonMatch(Predicate<> p) // 모두 만족하지 않는지
스트림의 모든 요소를 배열로 반환
Object[] toArray()
A[] toArray(IntFunction<A[]> generator)
스트림의 요소를 하나씩 줄여가면서(리듀싱) 계산한다.
Optional<T> reduce(BinaryOperator<T> accumulator)
T reduce (T identity, BinaryOperator<T> accumulator)
U reduce (U identity, BiFunction<U,T,U> accumulator, BinaryOperator<U> combiner)
스트림의 요소를 수집한다. 주로 요소를 그룹화하거나 분할한 결과를 컬렉션에 담아 반환하는데 사용된다.
R collect(Collector<T,A,R> collector)
R collect(Supplier<R> supplier, BiConsumer<R,T> accumulator, BiConsumer<R,R> combiner)
자세히 살펴보자😀
스트림 자르기 - skip(), limit()
Stream<T> skip (long n) // 앞에서부터 n개 건너뛰기
Stream<T> limit(long maxSize) // maxSize 이후의 요소는 잘라냄
예시 )
IntStream intStream = IntStream.rangeClosed(1, 10); // 12345678910
intStream.skip(3).limit(5).forEach(System.out::print); // 45678
스트림의 요소 걸러내기 - filter(), distinct()
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::println); // 123456
IntStream intStream = IntStream.rangeClosed(1, 10); // 12345678910
intStream.filter(i->i%2==0).forEach(System.out::print); // 246810
2의 배수 제거
intStream.filter(i->i%2!=0 && i%3!=0).forEach(System.out::print);
intStream.filter(i->i%2!=0).filter(i->i%3!=0).forEach(System.out::print);
중간 연산
2의 배수 빼고, 3의 배수빼면 1,5,7만 남음.
스트림 정렬하기 - sorted()
Stream<T> sorted() // 스트림 요소의 기본 정렬(Comparable)로 정렬
Stream<T> sorted(Comparator<? super T> compartor) // 지정된 Comparator로 정렬
strStream.sorted() 기본 정렬
strStream.sorted(Comparator.naturalOrder()) 같은 기본 정렬임 안에 생략되어 있는 것
strStream.sorted((s1,s2) -> s1.compareTo(s2)); // 람다식도 가능
strStream.sorted(String::compareTo); // 위와 동일함
출력 결과 대문자 먼저 나온다
CCaaabccdd
::는 뭐지? 어떻게 쓰는걸까? 궁금해서 검색 후 메소드 참조에 정리할 것임.
strStream.sorted(Comparator.reverseOrder()) // 기본 정렬의 역순
strStream.sorted(Comparator.<String>naturalOrder().reversed())
ddccbaaaCC
strStream.sorted(String.CASE_INSENSITIVE_ORDER) // 대소문자 구분안함
aaabCCccdd 대문자가 먼저 나온다. CCcc reverse 여서 ccCC가 나올것 같지만..😑
strStream.sorted(String.CASE_INSENSITIVE_ORDER.reversed())
ddCCccbaaa
strStream.sorted(Comparator.comparing(String::length)) // 길이 순 정렬
strStream.sorted(Comparator.comparingInt(String::length)) // no 오토박싱
bddCCccaaa
strStream.sorted(Comparator.comparing(String::length).reversed())
aaaddCCccb
- Comparator의 comparing()으로 정렬 기준을 제공
comparing(Function<T, U> keyExtractor)
comparing(Function<T, U> keyExtractor, Comparator<U> keyComparator)
studentStream.sorted(Comparator.comparing Student::getBan)) // 반별로 정렬
.forEach(System.out::println);
- 추가 정렬 기준을 제공할 때는 thenComparing()을 사용
thenComparing(Comparator<T> other)
thenComparing(Function<T, U> keyExtractor)
thenComparing(Function<T, U> keyExtractor, Comparator<U> keyComp)
studentStream.sorted(Comparator.comparing(Student::getBean) // 반별로 정리
.thenComparing(Student::getTotalScore) // 총점별로 정렬
.thenComparing(Student::getName)) // 이름별로 정렬
.forEach(System.out::println);
실 습 코 드
package Stream;
import java.util.Comparator;
import java.util.stream.Stream;
public class StreamSort {
public static void main(String[] args) {
Stream<Student> studentStream = Stream.of(
new Student("이자바", 3, 300),
new Student("김자바", 1, 200),
new Student("안자바", 2, 100),
new Student("박자바", 2, 150),
new Student("소자바", 1, 200),
new Student("나자바", 3, 290),
new Student("감자바", 3, 180)
);
studentStream.sorted(Comparator.comparing(Student::getBan)
.thenComparing(Comparator.naturalOrder()))
.forEach(System.out::println);
}
}
class Student implements Comparable<Student>{
String name;
int ban;
int totalScore;
Student(String name,int ban,int totalScore){
this.name = name;
this.ban = ban;
this.totalScore = totalScore;
}
public String toString() {
return String.format("[%s, %d, %d]",name, ban, totalScore);
}
public String getName() {return name;}
public int getBan() {return ban;}
public int getTotalScore() {return totalScore;}
// 총점 내림차순을 기본 정렬로 한다.
public int compareTo(Student s) {
return s.totalScore - this.totalScore;
}
}
Student는 기본 정렬을 Comparable로 구현하고 있고,
Comparable을 구현하면 compareTo 메서드를 오버라이딩 해야함.
그 오버라이딩 부분을 살펴보니 총점 내림차순을 기본 정렬로 한다.
studentStream.sorted(Comparator.comparing(Student::getBan)
// .thenComparing(Comparator.naturalOrder()))
.forEach(System.out::println);
주석 처리하면 기본정렬이 됨.
람다식으로 바꾸는 연습
// studentStream.sorted(Comparator.comparing(Student::getBan)
studentStream.sorted(Comparator.comparing((Student s) -> s.getBan())
.thenComparing(Comparator.naturalOrder()))
.forEach(System.out::println);
'Java' 카테고리의 다른 글
Java : Optional이란? (0) | 2021.09.04 |
---|---|
Java : 스트림의 연산,중간 연산(2) - 기초 (0) | 2021.09.04 |
Java : 스트림,스트림의 특징,스트림 만들기 - 기초 (0) | 2021.09.01 |
Java : GC(Garbage collector)에 대해서 - 기초 (0) | 2021.08.25 |
Java : JVM 이란? 자바 메모리 구조 (0) | 2021.08.25 |