일단 Stream.max() 를 공식문서에서 확인해보자.
Comparator의 구현체가 파라메터로 전달되어야 한다.
일단 max()를 적용하려는 객체에 객체들간의 순서를 지정할 수 있는 Comparable 인터페이스를 구현하겠다.
public class RacingCar implements Comparable<RacingCar> {
private static final int DEFAULT_POSITION = 0;
private int position = DEFAULT_POSITION;
// 중간 생략
@Override
public int compareTo(RacingCar anotherCar) {
return this.position - anotherCar.position;
}
}
compareTo()에 대한 설명을 잠깐 하자면, 현재 객체가 전달 받은 객체보다 큰 경우에는 양수, 같은 경우에는 0, 작은 경우에는 음수를 반환해야 한다.
이제 Stream.max() 를 사용해보자.
public class RacingCars {
private final List<RacingCar> cars;
// 중간 생략
private RacingCar searchAnyWinner() {
return cars.stream()
.max(RacingCar::compareTo)
.orElseThrow(() -> new RuntimeException("승자를 찾을 수 없다."));
}
}
cars를 stream으로 변환하고 객체들을 비교하여 최대 값을 찾아내는 로직이다.
max()는 Optional 객체를 반환하기 때문에 바로 get()을 하기 보다는 isPresent()와 같은 메소드로 null 체크를 진행하는 것이 좋다.
위의 코드에서는 orElseThrow()로 null일 때 예외를 발생하는 방식으로 대처하였다.
나는 여기서 조금 이상하다고 생각했다. max()의 파라메터에는 분명이 Comparator 구현체가 전달되어야 하는데, Comparable 구현체를 전달해도 정상적으로 동작하는 것으로 보였기 때문이다. 어떻게 된 일일까?
사실 위의 코드를 풀어 쓰면 아래와 같은 코드가 된다.
private RacingCar searchAnyWinner() {
return cars.stream()
.max(((o1, o2) -> o1.compareTo(o2)))
.orElseThrow(() -> new RuntimeException("승자를 찾을 수 없다."));
}
좀 더 풀어 써보겠다.
private RacingCar searchAnyWinner() {
return cars.stream()
.max(new Comparator<RacingCar>() {
@Override
public int compare(RacingCar o1, RacingCar o2) {
return o1.compareTo(o2);
}
})
.orElseThrow(() -> new RuntimeException("승자를 찾을 수 없다."));
}
사실 전달하고 있던 구현체는 Comparable이 아닌 Comparator였다.
이게 다 Method Reference 표기법에 무지했기 때문에 생긴 오해였다.. 🥲
출처
https://www.geeksforgeeks.org/stream-max-method-java-examples/
'개발 > 자바' 카테고리의 다른 글
추상화란? (2) | 2022.03.17 |
---|---|
compareTo()가 0을 반환하면 어떤 순서로 정렬되나? (0) | 2022.02.19 |
Comparable의 compareTo() 파헤치기 (0) | 2022.02.14 |
JUnit 사용법 (0) | 2022.02.11 |
[Java] clone()에 대해서 (0) | 2021.05.17 |
이전 댓글