equals () 및 hashcode ()를 사용하여 Java 객체 비교

이에서 자바 도전자 내용을 학습합니다 equals()hashcode()자바 프로그램에서 객체 비교를 효율적이고 쉽게 결합. 간단히 말해서, 이러한 메서드는 함께 작동하여 두 개체의 값이 동일한 지 확인합니다.  

없이 equals()하고하는 것은 hashcode()우리가 "매우 큰 만들어야 할 것이다 if객체에서 모든 필드를 비교,"비교. 이것은 코드를 정말 혼란스럽고 읽기 어렵게 만듭니다. 이 두 가지 방법을 함께 사용하면 더 유연하고 일관된 코드를 만들 수 있습니다.

Java Challengers 소스 코드를 가져옵니다.

Java에서 equals () 및 hashcode () 재정의

메서드 재정의 는 다형성을 활용하기 위해 부모 클래스 또는 인터페이스의 동작을 하위 클래스에 다시 작성 (재정의)하는 기술입니다. ObjectJava의 모든 것에 는 equals()hashcode()메서드가 포함되어 있지만 제대로 작동하려면 재정의해야합니다.

얼마나 무시 작품을 이해하기 위해 equals()그리고   hashcode(), 우리는 핵심 자바 클래스에서 구현을 공부할 수 있습니다. 아래는 수업 의 equals()방법입니다 Object. 메서드는 현재 인스턴스가 이전에 전달 된 것과 동일한 지 확인합니다 Object.

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

hashcode()메소드를 오버라이드 (override)되지는의 기본 방법 Object클래스는 호출됩니다. 이것은 C와 같은 다른 언어로 실행되고 객체의 메모리 주소와 관련된 일부 코드를 반환 하는 네이티브 메서드 입니다. (JDK 코드를 작성하지 않는 한이 방법이 어떻게 작동하는지 정확히 아는 것은 중요하지 않습니다.)

 @HotSpotIntrinsicCandidate public native int hashCode(); 

equals()hashcode()방법이 무시되지 않습니다, 당신은 위의 방법 대신 호출 볼 수 있습니다. 이 경우 메서드는 두 개 이상의 객체가 동일한 값을 갖는지 확인하는 equals()and 의 실제 목적을 충족하지 않습니다 hashcode().

일반적으로 재정의 equals()할 때 hashcode().

equals ()로 객체 비교

equals()메소드를 사용하여 Java에서 객체를 비교합니다. 두 개체가 동일한 지 확인하기 위해 equals()개체의 속성 값을 비교합니다.

 public class EqualsAndHashCodeExample { public static void main(String... equalsExplanation) { System.out.println(new Simpson("Homer", 35, 120) .equals(new Simpson("Homer",35,120))); System.out.println(new Simpson("Bart", 10, 120) .equals(new Simpson("El Barto", 10, 45))); System.out.println(new Simpson("Lisa", 54, 60) .equals(new Object())); } static class Simpson { private String name; private int age; private int weight; public Simpson(String name, int age, int weight) { this.name = name; this.age = age; this.weight = weight; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Simpson simpson = (Simpson) o; return age == simpson.age && weight == simpson.weight && name.equals(simpson.name); } } } 

첫 번째 비교 equals()에서 현재 개체 인스턴스를 전달 된 개체와 비교합니다. 두 객체의 값이 같으면 equals()을 반환 true합니다.

두 번째 비교 equals()에서 전달 된 객체가 null 인지 또는 다른 클래스로 입력되었는지 확인합니다. 다른 클래스라면 객체는 같지 않습니다.

마지막으로 equals()개체의 필드를 비교합니다. 두 개체에 동일한 필드 값이 있으면 개체는 동일합니다.

개체 비교 분석

이제 우리의 main()방법 에서 이러한 비교 결과를 보겠습니다 . 먼저 두 Simpson개체를 비교 합니다.

 System.out.println(new Simpson("Homer", 35, 120).equals(new Simpson("Homer", 35, 120))); 

여기에있는 개체는 동일하므로 결과는입니다 true.

다음으로 두 Simpson개체를 다시 비교 합니다.

 System.out.println(new Simpson("Bart", 10, 45).equals(new Simpson("El Barto", 10, 45))); 

여기에있는 개체는 거의 동일하지만 이름은 Bart와 El Barto가 다릅니다. 따라서 결과는 false.

마지막으로 Simpson객체와 객체 클래스의 인스턴스를 비교해 보겠습니다 .

 System.out.println(new Simpson("Lisa", 54, 60).equals(new Object())); 

이 경우 결과는 false클래스 유형이 다르기 때문입니다.

equals () 대 ==

언뜻보기에는 ==연산자와 equals()방법이 동일한 작업을 수행하는 것처럼 보일 수 있지만 실제로는 다르게 작동합니다. ==오퍼레이터는 두 개체 참조가 동일한 객체를 가리 여부를 비교한다. 예를 들면 :

 System.out.println(homer == homer2); 

첫 번째 비교에서는 연산자 Simpson를 사용하여 두 개의 다른 인스턴스를 인스턴스화했습니다 new. 이 때문에 변수 homer및 메모리 힙에서 homer2다른 Object참조를 가리 킵니다 . 그래서 우리는 false그 결과를 얻게 될 것 입니다.

System.out.println(homer.equals(homer2)); 

두 번째 비교에서는 equals()메서드를 재정의합니다 . 이 경우 이름 만 비교됩니다. 두 Simpson개체 의 이름 이 "Homer" 이기 때문에 결과는입니다 true.

hashcode ()로 객체를 고유하게 식별

우리는 hashcode()객체를 비교할 때 성능을 최적화 하는 방법을 사용 합니다. 실행   hashcode()하면 프로그램의 각 개체에 대한 고유 ID가 반환되므로 개체의 전체 상태를 훨씬 쉽게 비교할 수 있습니다.

객체의 해시 코드가 다른 객체의 해시 코드와 같지 않으면 equals()메서드 를 실행할 이유가 없습니다 . 두 객체가 동일하지 않다는 것을 알뿐입니다. 반면에 해시 코드 동일한 경우 equals()메서드를 실행 하여 값과 필드가 동일한 지 확인 해야합니다 .

다음은 hashcode().

 public class HashcodeConcept { public static void main(String... hashcodeExample) { Simpson homer = new Simpson(1, "Homer"); Simpson bart = new Simpson(2, "Homer"); boolean isHashcodeEquals = homer.hashCode() == bart.hashCode(); if (isHashcodeEquals) { System.out.println("Should compare with equals method too."); } else { System.out.println("Should not compare with equals method because " + "the id is different, that means the objects are not equals for sure."); } } static class Simpson { int id; String name; public Simpson(int id, String name) { this.id = id; this.name = name; } @Override public boolean equals(Object o)  if (this == o) return true; if (o == null  @Override public int hashCode() { return id; } } } 

hashcode()항상 동일한 값을 반환하는 A 는 유효하지만 그다지 효과적이지 않습니다. 이 경우 비교는 항상을 반환 true하므로 equals()메서드가 항상 실행됩니다. 이 경우 성능 향상이 없습니다.  

컬렉션과 함께 equals () 및 hashcode () 사용

The Set interface is responsible for ensuring no duplicate elements will be inserted in a Set subclass. The following are some of the classes that implement the Set interface:

  • HashSet
  • TreeSet
  • LinkedHashSet
  • CopyOnWriteArraySet

Only unique elements may be inserted into a Set, so if you want to add an element to the HashSet class (for example), you must first use the equals() and hashcode() methods to verify that the element is unique. If the equals() and hashcode()methods weren’t overridden in this case, you would risk inserting duplicate elements in the code.

In the code below, we’re using the add method to add a new element  to a HashSet object. Before the new element is added, HashSet checks to see whether the element  already exists in the given collection:

 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; 

If the object is the same, the new element won’t be inserted.

Hash collections

Set isn’t the only collection that makes use of equals() and hashcode(). HashMap, Hashtable, and LinkedHashMap also require these methods. As a rule, if you see a collection that has the prefix of “Hash,” you can be sure that it requires overriding the hashcode() and equals() methods to make their features work properly.  

Guidelines for using equals() and hashcode()

You should only execute an equals() method for objects that have the same unique hashcode ID. You should not execute equals() when the hashcode ID is different.

Table 1. Hashcode comparisons

If the hashcode() comparison ... Then …
returns true execute equals()
returns false do not execute equals()

This principle is mainly used in Set or Hash collections for performance reasons.

Rules for object comparison

When a hashcode() comparison returns false, the equals() method must also return false. If the hashcode is different, then the objects are definitely not equal.

Table 2. Object comparison with hashcode()

When the hashcode comparison returns ... The equals() method should return ...
true true or false
false false

When the equals() method returns true, it means that the objects are equal in all values and attributes. In this case,  the hashcode comparison must be true as well.

Table 3. Object comparison with equals()

When the equals() method returns ... The hashcode() method should return ...
true true
false true or false

Take the equals() and hashcode() challenge!

It’s time to test your skills with the equals() and hashcode() methods.  Your goal in this challenge is to figure out the output of the two equals() method comparisons and guess the size of the Set collection.

To start, study the following code carefully:

 public class EqualsHashCodeChallenge { public static void main(String... doYourBest) { System.out.println(new Simpson("Bart").equals(new Simpson("Bart"))); Simpson overriddenHomer = new Simpson("Homer") { public int hashCode() { return (43 + 777) + 1; } }; System.out.println(new Simpson("Homer").equals(overriddenHomer)); Set set = new HashSet(Set.of(new Simpson("Homer"), new Simpson("Marge"))); set.add(new Simpson("Homer")); set.add(overriddenHomer); System.out.println(set.size()); } static class Simpson { String name; Simpson(String name) { this.name = name; } @Override public boolean equals(Object obj) { Simpson otherSimpson = (Simpson) obj; return this.name.equals(otherSimpson.name) && this.hashCode() == otherSimpson.hashCode(); } @Override public int hashCode() { return (43 + 777); } } } 

Remember, analyze the code first, guess the result, and then run the code. Your goal is to improve your skill with code analysis and absorb core Java concepts to make your code more powerful. Choose your answer before checking the correct answer below.

 A) true true 4 B) true false 3 C) true false 2 D) false true 3 

What just happened? Understanding equals() and hashcode()

In the first equals() method comparison, the result is true because the state of the object is exactly the same and the hashcode() method returns the same value for both objects.

In the second equals() method comparison, the hashcode() method is being overridden for the overridenHomer variable. The name is “Homer” for both Simpson objects, but the hashcode() method returns a different value for overriddenHomer. In this case, the final result from the the equals() method will be false because the method contains a comparison with the hashcode.

You might notice that the size of the collection is set to hold three Simpson objects. Let’s check this in a detailed way.

The first object in the set will be will be inserted normally:

 new Simpson("Homer"); 

The next object will be inserted normally, as well, because it holds a different value from the previous object:

 new Simpson("Marge"); 

Finally,  the following Simpson object has the same value as the first object. In this case the object won’t be inserted:

 set.add(new Simpson("Homer")); 

아시다시피 overridenHomer객체는 일반 Simpson(“Homer”)인스턴스화 와 다른 해시 코드 값을 사용합니다 . 이러한 이유로이 요소는 컬렉션에 삽입됩니다.

 overriddenHomer; 

정답

이 Java Challenger에 대한 대답은 B 입니다. 출력은 다음과 같습니다.

 true false 3 

비디오 도전! equals () 및 hashcode () 디버깅

디버깅은 프로그래밍 개념을 완전히 흡수하는 동시에 코드를 개선하는 가장 쉬운 방법 중 하나입니다. 이 비디오에서는 Java equals()hashcode()과제를 디버깅하고 설명하는 동안 따라갈 수 있습니다 .