2023-java-study / book-study

북 스터디 기록 레포지토리
0 stars 0 forks source link

[Item 11] hashcode 생성 시 필드의 표준형? #34

Closed gmelon closed 1 year ago

gmelon commented 1 year ago

p.69 2-ii계산이 더 복잡해질 것 같으면, 이 필드의 표준형을 만들어 그 표준형의 hashcode를 호출한다 라고 되어있습니다.

필드의 표준형이라는게 toString()에서와 마찬가지로 정해진 표현 방법 일까요? 표준형의 hashcode를 호출한다 라는 말이 잘 이해되지 않습니다. 이게 어떤 의미라고 생각하시나요???

ssstopeun commented 1 year ago
public class CaseInsenstiveString {
    private final String value;
    public CaseInsenstiveString(String value){
        this.value= Objects.requireNonNull(value);
    }

    @Override
    public boolean equals(Object o){
        if(o instanceof CaseInsenstiveString){
            // 대소문자를 통일시켜 비교하는 방식
            return value.equalsIgnoreCase(((CaseInsenstiveString) o).value);
        }
        return false;
    }
}

이 코드는 아이템 10에서 나왔던 CaseInsensitiveString인데 여기서 보면 equalsIgnoreCase() 메서드에서 toUpperCase / toLowerCase를 통해 두 문자열을 비교하게 됩니다. 이렇게 되면 비교할때마다 비용이 발생하니

public class CaseInsenstiveString2 {
    private final String value;

    //대문자로 변경해놓은 표준형 필드
    private final String canonicalValue;

    public CaseInsenstiveString2(String value){
        this.value = Objects.requireNonNull(value);
        this.canonicalValue =value.toUpperCase();
    }

    @Override
    public boolean equals(Object o){
        if(o instanceof CaseInsenstiveString2){
            return canonicalValue.equals(((CaseInsenstiveString2)o).canonicalValue);
        }
        return false;
    }
}

이렇게 대문자로 바꿔놓은 표준형을 만들어놓고 비교하는 방식이 있더라고요.

그래서 여기서 확장해서 생각해보았을 때

@Override
    public int hashCode(){
        if(canonicalValue==null){
            return 0;
        }
        int result = canonicalValue.hashCode();
        return result;
    }

hashCode를 override 할 때에도 대소문자를 하나로 통일시켜서 hashCode로 생성해주기에 계산이 복잡해지니 대문자로 만들어놓은 표준형을 사용해 표준형의 hashCode를 호출하자는 의미로 해석했습니다.