Algorithms

[JAVA] 해싱 동작 방식

kkkkkkkkkkkk 2022. 1. 17. 14:43

학습 내용

  • 해시 코드의 동작 방식을 이해합니다.

 

불변 객체

public class Book {

    private final String name;

    public Book(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        return this.name.toString().equals(o.toString());
    }

    @Override
    public int hashCode() {
        int sum = 0;
        for (int i = 0; i < name.length(); i++) {
            sum += name.charAt(i);
        }
        return sum;
    }
}

 

두 메서드 equals() 메서드가 true를 반환하면 해시 코드도 같아야 하는데

불변 객체를 표현 하기 위해 해시 코드만 같게 나오고 equlas 메서드는 false 가 나올 것입니다. 두 객체는 같아야 할 필요는 없습니다.

 

테스트

Book book = new Book("apple");
Book book1 = new Book("apple");

System.out.println(book.equals(book1));
System.out.println(book.hashCode() + ", " + book1.hashCode());

 

결과

객체가 같나요? : false
해시 코드 : ? 530, 530

 


가변 객체

인스턴스의 값을 변형 시켜버리면 해시 코드의 값이 변경 되므로 하위 맵에서 조회가 불가능 합니다. 따라서 해싱을 사용하는 자료구조에서 가변 객체를 키로 하는 것을 위험합니다.

 

public class Store {

    private String name;

    public Store(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Store{" +
                "name='" + name + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        return this.name.toString().equals(o.toString());
    }

    @Override
    public int hashCode() {
        int sum = 0;
        for (int i = 0; i < name.length(); i++) {
            sum += name.charAt(i);
        }
        return sum;
    }
}

 

테스트

Store book1 = new Store("Word1");
Store book2 = new Store("Word1");

System.out.println(book1.equals(book2));
System.out.println(book1.hashCode());
System.out.println(book2.hashCode());

book1.setName("Word3");
System.out.println(book1.hashCode());
System.out.println(book2.hashCode());

 

결과

false
461
461
463 // 해시 코드가 달라짐
461 

 


정리 

해싱을 사용하는 자료구조에 가변 객체를 사용하면 객체의 해시 코드들의 변형이 생겨 기존에 저장된 맵에 조회를 할 때 엉뚱 한 곳을 조회하기 때문에 key 값을 가변 객체로 사용하는 것은 피해야합니다.