equals()메소드,객체 해시코드(hashCode())

서이·2022년 12월 4일
0

Java

목록 보기
26/27

객체 비교(equals())

equals()

두 객체의 내용이 같은지 확인하는 Method

1. 객체를 비교해보자

public static void main(String args[])
{
        User user1 = new User("shlee", 20);
        User user2 = new User("shlee", 20);
        System.out.println(user1.equals(user2));
         // 결과는 false
}


public class User
{
    private String name;
    private int age;

    public User(String name, int age)
    {
        this.name = name;
        this.age = age;
    }
}

의미상 내용이 같은 객체인데 user1과 user2는 같다고 봐야하는데,

비교시에 false가 나온다.

결과값이 왜 false 일까??

object class의 equals 함수를 사용하기 때문이다.
// Object class의 내용을 확인해보자


    public boolean equals(Object obj) {
        return (this == obj);
    }
 

Object 의 equals 함수는 코드를 보면 "==" 비교이다.

즉 주소값 비교로 되어 있다.

String을 비교해 보자

        String aa = "cc";
        String bb = "cc";
        System.out.println(aa.equals(bb)); 
        
        //결과 true

그럼 false가 나와야지 왜 true 인데??

String class의 equals 함수를 사용하기 때문이다
String의 equals는 재정의( 오버라이드 ) 되어 있기 때문이다.

즉 object equals와는 소스가 다르다.


   public class Member {
   		public String id;
   
   public Member(String id){
   	this.id = id; 
   }
   
   @Override
   public boolean equals(Object obj) {
   	if(obj instanceof Member){  //매개값이 Member 타입인지 확인
    	Member member = (Member) obj;
        if(id.equals(member.id)){
        	return true;
        } // Member 타입으로 강제 타입 변환하고 id 필드값이 동일한지
          // 검사한 후, 동일하다면 true를 리턴
    }
    return false; // 매개값이 Member 타입이 아니거나 id 필드값이
    			  // 다른 경우 false를 리턴
   }
 }

모든 클래스는 Object의 equals 를 상속 받고 있고,

String class는 Object의 equals를 재정의 했다고 할수 있다.

public class MemberExample{
	public static void main(String[] args){
    	Member obj1 = new Member("blue");
        Member obj2 = new Member("blue");
        Member obj3 = new Member("green");
        
        if(obj1.equals(obj2)){
        	System.out.println("obj1과 obj2는 동등합니다.");
        } else {
        	System.out.println("obj1과 obj2는 동등하지 않습니다.");
            
        if(obj1.equals(obj3)){
        	System.out.println("obj1과 obj3는 동등합니다.");
        } else {
        	System.out.println("obj1과 obj3는 동등하지 않습니다.");  

객체 해시코드(hashConde())

객체 해시코드란 객체를 식별할 하나의 정수값을 말한다. Object의 hashCode() 메소드는 객체의 메모리 번지를 이용해서 해시코드를 만들어 리턴하기 때문에 객체마다 다른 값을 가지고 있다. 논리적 동등 비교 시 hashCode()를 오버라이딩할 필요성이 있는데 15장에서 배울 컬렉션 프레임워크에서 HashSet, HashMap, Hashtable은 다음과 같은 방법으로 두 객체가 동등한지 비교한다. 우선 hashCode() 메소드를 실행해서 리턴된 해시코드 값이 같은지를 본다. 해시코드 값이 다르면 다른 객체로 판단하고, 해시코드 값이 같으면 equals() 메소드로 다시 비교한다. 그렇기 때문에 hashCode() 메소드가 treu가 나와도 equals()의 리턴값이 다르면 다른 객체가 된다.

public class Key {
	public int number;
    
    public Key(int number) {
    	this.number = number;
    }
    
    @Override
    public boolean equals(Object obj){
    	if(obj instanceof Key) {
        	Key compareKey = (Key) obj;
            if(this.number == compareKey.number) {
             return true;
            }
        }
        return false;
      }
 }

이런 경우 HashMap의 식별키로 Key 객체를 사용하면 저장된 값을 찾아오지 못한다. 왜냐하면 number 필드값이 같더라도 hashCode() 메소드에서 리턴하는 해시코드가 다르기 때문에 다른 식별키로 인식하기 때문이다. 다음 예제는 "new key(1)" 객체로 "홍길동"을 저장하고, 다시 "new Key(1)" 객체로 저장된 "홍길동"을 읽을려고 했지만 결과는 null이 나온다.

  
  	public static void main(String[] args) {
    	//Key 객체를 식별키로 사용해서 String 값을 저장하는 HashMap 객체 생성
       HashMap<Key,String> hashMap = new HashMap<Key,String>();
       
       //식별키 "new Key(1)"로 "홍길동"을 저장함
       hashMap.put(new Key(1), "홍길동");
       
       //식별키 "new Key(1)"로 "홍길동"을 읽어옴
       String value = hashMap.get(new Key(1));
       System.out.println(value);
     }
  

의도한 대로 "홍길동"을 읽을려면 다음과 같이 재정의한 hashCode() 메소드를 Key 클래스에 추가하면 된다. hashCode()의 리턴값을 number 필드값으로 했기 때문에 저장할 때의 "new Key(1)"과 읽을 때의 "new Key(1)"은 같은 해시코드가 리턴된다.

public class Key {
 	...
 	@Override
 	public int hashCode(){
 		return number;
 	}
}

전체적인 코드를 보자면

import java.util.HashMap;

public class Key {
	public int number;
    
    public Key(int number) {
    	this.number = number;
    }
    
    @Override
    public boolean equals(Object obj){
    	if(obj instanceof Key) {
        	Key compareKey = (Key) obj;
            if(this.number == compareKey.number) {
             return true;
            }
        }
        return false;
      }
      
    @Override
 	public int hashCode(){
 		return number;
 	}
    	
      	public static void main(String[] args) {
        	//Key 객체를 식별키로 사용해서 String 값을 저장하는 HashMap 객체 생성
           HashMap<Key,String> hashMap = new HashMap<Key,String>();
           
           //식별키 "new Key(1)"로 "홍길동"을 저장함
           hashMap.put(new Key(1), "홍길동");
           
           //식별키 "new Key(1)"로 "홍길동"을 읽어옴
           String value = hashMap.get(new Key(1));
           System.out.println(value);
         }
      }

저장할 때의 new Key(1)과 읽을 때의 new Key(1)은 사실 서로 다른 객체이지만 HashMap은 hashCode()의 리턴값이 같고, equals() 리턴값이 true가 나오기 때문에 동등 객체로 평가한다.
즉, 같은 식별키로 인식한다는 뜻이다. 결론적으로 말해서 객체의 동등 비교를 위해서는 Object의 동일한 해시코드가 리턴되도록 해야한다.

profile
작성자 개인이 잊을 때마다 보라고 정리한 글

0개의 댓글

관련 채용 정보