홈 › 중급 › 07 / 9

Object 메서드와 비교

equals, hashCode, toString, Comparable
섹션 7진행 0 / 9

6. 연습 문제

문제 1

Money(BigDecimal amount, String currency) 클래스를 일반 클래스로 만들고, 통화가 같고 금액이 compareTo 기준으로 같으면 동등하도록 equals/hashCode 를 작성하세요. new Money("1.0", "KRW") 와 new Money("1.00", "KRW") 가 HashSet 에서 하나로 합쳐져야 합니다.

정답 보기
java
public final class Money {
    private final BigDecimal amount; private final String currency;
    public Money(String amount, String currency) { this.amount = new BigDecimal(amount); this.currency = currency; }
    @Override public boolean equals(Object o) {
        return o instanceof Money m && currency.equals(m.currency) && amount.compareTo(m.amount) == 0;
    }
    @Override public int hashCode() { return Objects.hash(amount.stripTrailingZeros(), currency); }   // 1.0 과 1.00 의 해시를 같게: 뒤 0 제거 후 계산
}

hashCode 에서 amount 를 그대로 쓰면 1.0 과 1.00 의 해시가 달라 규약(같으면 해시도 같다)을 어깁니다. stripTrailingZeros() 로 정규화한 값을 해시에 넣어야 합니다. 더 간단한 방법은 생성자에서 스케일을 통일하고 record 로 만드는 것입니다(변형 3).

문제 2

Order 를 "고객명 오름차순(null 은 마지막) → 날짜 내림차순 → 금액 내림차순" 으로 정렬하는 Comparator 를 한 식으로 작성하고, Main 의 주문 4건에 적용한 결과를 예측한 뒤 실행으로 확인하세요.

정답 보기
java
Comparator<Order> cmp = Comparator
        .comparing(Order::customer, Comparator.nullsLast(Comparator.naturalOrder()))
        .thenComparing(Order::date, Comparator.reverseOrder())
        .thenComparing(Order::amount, Comparator.reverseOrder());
orders.sort(cmp);
// 예측: kim(1) → lee(2) → park(3) → null(4). 같은 고객이 없으므로 2·3차 기준은 이 데이터에서 작동하지 않는다

thenComparing(키 추출, 비교자) 형태로 각 단계마다 방향을 따로 줄 수 있습니다. reversed() 는 앞의 전체를 뒤집으므로 중간에 끼우면 의도와 달라집니다. 단계별 방향은 Comparator.reverseOrder() 를 두 번째 인자로 주는 것이 안전합니다.

문제 3

Point 에 hashCode 를 추가한 뒤, HashSet 에 넣고 필드를 바꿀 수 없음(final)을 확인하세요. 그런 다음 Point 를 record 로 바꾸면 소스가 몇 줄로 줄어드는지, record 로 바꿀 수 없는 경우는 어떤 경우인지 설명하세요.

정답 보기
java
public record Point(int x, int y) { }   // equals·hashCode·toString·접근자·생성자 전부 자동. 12줄 → 1줄

record 로 바꿀 수 없는 경우: (1) 필드 일부만 식별자인 엔티티(Member 의 id), (2) 생성 후 값이 바뀌어야 하는 객체(record 는 모든 필드가 final), (3) 다른 클래스를 상속해야 하는 경우(record 는 상속 불가, 인터페이스 구현만 가능), (4) JPA 엔티티처럼 기본 생성자와 세터를 요구하는 프레임워크 대상.