在網上搜到一條題目挺有意思的,需要好好理解 Java 裡的 hashcode()
和 Equals()
# Question
- Question: Why the amap size is 3? Instead of 4 even though we called put() method 3 times *
- Question 2: Fixed the code(Apple class) * to let the map treat the apples with the same color as the same key. * So the amap size will be 1. Output should be "map size is 1" * * DO NOT Change the main method */
# Code
package com.tiffanyiong; | |
import java.util.Collection; | |
import java.util.Collections; | |
import java.util.List; | |
import java.util.Scanner; | |
import java.util.*; | |
public class Main { | |
public static void main(String[] args) { | |
Apple a = new Apple("red", 10); | |
Apple a1 = new Apple("red", 10); | |
Apple a2 = a; | |
Apple a3 = new Apple("red", 10); | |
Map<Apple, String> amap = new HashMap<>(); | |
amap.put(a,"one apple"); | |
amap.put(a1,"two apples"); | |
amap.put(a2,"three apples"); | |
amap.put(a3,"four apples"); | |
System.out.printf("map size is %s \n", amap.size()); | |
System.out.println(a3.equals(a1)); | |
} | |
} | |
class Apple { | |
private int price; | |
private String color; | |
HashSet<String> set = new HashSet(); | |
public Apple(String color, int price) { | |
this.price = price; | |
this.color = color; | |
} | |
public int getPrice() { | |
return price; | |
} | |
public void setPrice(int price) { | |
this.price = price; | |
} | |
public String getColor() { | |
return color; | |
} | |
public void setColor(String color) { | |
this.color = color; | |
} | |
@Override | |
public String toString() { | |
return "Apple{" + | |
"color='" + color + '\'' + | |
'}'; | |
} | |
} |
# 解答
==
Operator 和 java 裡 equals () 是有區別,可以想像==
是個 pointer, 我只是把 a2 point to a 這個 APPLE 的 Object,所以第一題應該是 3 個 objects, size 也只會是 3, 由始至終只有 3 個 objects- 需要重新寫 hashcode () 和 equals () 的方法
# Object 裡的 equals ()
Human a = new Human("tiff"); | |
Human b = a; | |
a.equals(b); | |
Human c = new Human("tiff"); | |
a.equals(c); // false |
(click the answer below)
上面代碼的
a.equals(b)
是___?上面代碼的
a.equals(c)
是___?首先看一下,為甚麼
a.equals(c)
是錯的- 因為 Object Class 裡面的
equals()
只是對比obj == obj
, 而此時 c 是新的一個 object, 儘管裡面的值是相等,但並不代表它們是一樣。 - 比如:同時有兩個人叫小明,但他們是不是同一個人?他們只是名字相同而已。
可是,不啊,這就是小明,這就是一個人而已! 那我們可以 Override equals ()!
但是在此之前,要先看看 String 裡的equals()
- 因為 Object Class 裡面的
# String class - equals()
我們再來看看這個代碼
String s1 = new String("ab"); | |
String s2 = new String("ab"); | |
System.out.println(s1.equals(s2)); |
- 上面代碼的
s1.equals(s2)
是___?
String 的equals()
沒錯,如果看源碼的話,String 裡的 equals () 是重新寫的!
這不再像之前的 object 一樣 obj == obj
,這次是比較 Obj 裡面的值啦~
所以我們知道 String 和 Object 裡的 equals () 是比較不樣的的東西後,我們就知道了,其實可以寫自己的 equals ()! 不過我們還需要知道 hashCode ()
題外話: StringBuilder
沒有 Override equals()
, 不能用來 Compare, 2 個 StringBuilder
的 object 用 equals()
肯定不對啦
# hashCode
- Each object has a unique memory address which helps the object class hashCode to generate an unique hashcode for each object.
- it uses memory address, then do some calculation
JVM gen't get the actual memory address, that's why it do some pre-processing to create a hashcode
A Good HashCode:
a good hashcode() should return a distinct integer for each object (as much as possible). tow different object can have the same hashcode();
- same hashcode != same object
- but if the objects are the same, then the hashcode will be the same
# Solution Code
@Override | |
public boolean equals(Object o) { | |
if (this == o) return true; | |
if (o == null || getClass() != o.getClass()) return false; | |
Apple apple = (Apple) o; | |
return color.equals(apple.color) | |
} | |
@Override | |
public int hashCode() { | |
return Objects.hash(color); | |
} |