스트림 자르기 - skip(), limit()
skip(n)은 n만큼 요소를 건너뛰는 것이고,
limit(n)은 n만큼 요소의 개수를 제한한다.
IntStream intStream = IntStream.rangeClosed(1,10); // 1~10의 요소를 가진 스트림
intStream.skip(3).limit(5).forEach(System.out::print); // 1,2,3건너뛰고 4~8까지 5개 출력
스트림 요소 걸러내기 -filter(), distinct()
distinct()는 스트림에서 중복된 요소들을 제거하고,
filter()는 주어진 조건에 맞지 않는 요소를 걸러낸다.
IntStream int Stream = IntStream.of(1,2,2,3,3,3,4,5,6);
intStream.distinct().forEach(System.out::print); // 123456
IntStream intStream = IntStream.rangeClosed(1,10);
intStream.filter(i ->i%2 != 0).filter(i -> i%3 != 0).forEach(System.out::print); // 157
정렬 - sorted()
스트림 원소를 정렬해준다. 매개변수에 Comparator를 넣어주면 그에 따른 정렬을 시행한다.
// 문자열 기준
strStream.sorted() // 기본정렬
strStream.sorted(Comparator.reverseOrder()) // 역순 정렬
예제 - 반별로 정렬한 후 내부 클래스에서 총점별로 내림차순 정렬한다.
import java.util.*;
import java.util.stream.*;
class StreamEx1 {
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).toString();
}
String getName() { return name;}
int getBan() { return ban;}
int getTotalScore() { return totalScore;}
// 총점 내림차순을 기본 정렬로 한다.
public int compareTo(Student s) {
return s.totalScore - this.totalScore;
}
}
변환 - map()
원하는 필드만 뽑아내거나 특정 형태로 변환해준다.
Stream<File> fileStream = Stream.of(new File("ex1.java"), ....);
fileStream.map(File::getName) // Stream<File> -> Stream<String>
.filter(s -> s.indexOf('.') != -1) // 확장자가 없는것은 제외
.map(s -> s.substring(s.indexOf('.')+1)) // 확장자이름만 뽑기
.map(String::toUpperCase) // 모두 대문자로 변환
.distinct() //중복제거
.forEach(System.out::print); // 중간 연산 다 시행한 결과 원소 모두 출력
조회 - peek()
연산과 연산 사이에 올바르게 처리되었는지 확인하고 싶을 때 사용한다.
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::print);
mapToInt(), mapToLong(), mapToDouble()
스트림의 요소를 숫자로 변환하는 경우에 쓰인다.
//학생클래스가 들어있는 스트림에서 getTotalScore메서드를 통해 IntStream으로 변경
IntStream studentScoreStream = studentStream.mapToInt(Student::getTotalScore);
// .sum()메서드를 통해 총합계 구하기
int allTotalScore = studentScoreStream.sum();
Stream<T>는 count()만 지원하는데, IntStream같은 기본형 스트림은 숫자를 다루는데 편리한 메서드를 제공한다.
IntStream기준으로 설명
메서드 | 설 명 |
int sum() | 스트림의 모든 요소의 총합 |
OptionalDouble average() | sum() / (double)count() |
OptionalInt max() | 스트림의 요소 중 제일 큰 값 |
OptionalInt min() | 스트림의 요소 중 제일 작은 값 |
sum()을 제외한 다른 메서드들은 단순히 0을 반환할 수 없어서 Optional클래스를 씀. 추후 설명.
이 메서드들은 최종연산이기때문에 호출 후에 스트림이 닫힌다.
만약 하나의 스트림에서 이러한 메서드들을 여러번 써야한다면 summaryStatistics() 메서드를 사용하면 된다.
IntSummaryStatistics stat = scoreStream.summaryStatistics();
long totalCount = stat.getCount();
long totalScore = stat.getSum();
double avgScore = stat.getAverage();
int minScore = stat.getMin();
int maxScore = stat.getMax();
flatMap() - Stream<T[]> 를 Stream<T>로 변환
스트림의 요소가 배열이거나 map()의 연산결과가 배열인 경우,
즉 Stream<T[]>인 경우, Stream<T>로 다루는 것이 더 편리할 때가 있다.
이럴 경우에 map() 대신 flatMap()을 통해 해결한다.
Stream<String[]>을 'map(Arrays:stream)' 변환한 결과는 Stream<Stream<String>>이 된다.
Stream<string[]>을 'flatmap(Arrays:stream)' 변환한 결과는 Stream<String>이 된다.
Optional<t> 와 OptionalInt
Optional클래스
Optional<T>는 제네릭 클래스로 'T타입의 객체'를 감싸는 래퍼 클래스이다.
Optional타입의 객체에는 모든 타입의 참조변수를 담을 수 있다.
최종 연산의 결과를 그냥 반환하는 게 아니라 Optional객체에 담아서 반환하는 것이다.
이처럼 객체에 담아서 반환을 하면, 반환된 결과가 null인지 if문으로 체크하는 대신,
Optional에 정의된 메서드 isNull() 등을 통해 확인할 수 있다.
그렇기 때문에 if문이 없어도 NullPointerException이 발생하지 않는다.
Optional객체 생성
Optional.of() 와 Optional.ofNullable() 로 생성가능하다.
만일 참조변수의 값이 null일 가능성이 있으면, ofNullable()을 사용한다.
Optional<String> optVal = Optional.of("abc");
Optional<String> optVal = Optional.ofNullable(null);
//기본값으로 초기화할 때는 empty() 사용할 것.
Optional<String> optVal = Optional.empty();
Optional객체의 값 가져오기
get() 사용.
값이 null일 경우에 NoSuchElementException이 발생하며, 이럴땐 orElse() 메서드로 대체할 값을 지정할 수 있다.
Optional<String> optVal = Optional.of("abc");
String str1 = optVal.get();
String str2 = optVal.orElse(""); // null일경우, "" 반환
orElseGet()은 null을 대체할 값을 반환하는 람다식을 지정 가능
orElseThrow()는 null일 때 지정된 예외 발생.
Optional객체도 Stream처럼 filter(), map(), flatMap() 사용 가능하다. 만약, null값이면 이 메서드들은 아무일도 하지 않는다.
Stream클래스에 정의된 메서드 중 Optional<T>를 반환하는 것들은 다음과 같다.
findAny()
findFirst()
max()
min()
reduce()
OptionalInt, OptionalLong, OptionalDouble
기본형을 값으로하는 Optional이다.
OptionalInt | getAsInt() |
OptionalLong | getAsLong() |
OptionalDouble | getAsDouble() |
'Language > Java' 카테고리의 다른 글
[Java] Garbage Collection(GC) 가비지 컬렉션 (0) | 2022.04.03 |
---|---|
[Java] 자바 스트림(stream) 사용법 3 - 최종 연산 (0) | 2022.03.16 |
[Java] 자바 스트림(stream) 사용법 1 - 특징과 생성 (0) | 2022.03.16 |
[Java] 람다식(Lambda expression)과 함수형 인터페이스(Functional Interface) (0) | 2022.03.16 |
[Java] 쓰레드 8 - fork & join 프레임 워크 (0) | 2022.03.14 |
댓글