2014-11-22 24 views
0

大家都知道,這是更好地使用不可變類爲重點的HashMap,如果我們改變對象的狀態,則重新計算JVM的哈希代碼爲對象。更改的hashCode運行

有人可以使其中改變對象的狀態,它的哈希碼更改後的例子嗎? (在運行時)

回答

1
public class Something { 

    public String blah; 

    public int hashCode() { 
     return blah.hashCode(); 
    } 
} 

顯然你會不太代碼這樣的事情(你有一個getter和一個setter和hashCode將是一個更復雜些,並且你有一個equals()太)但這符合你的問題的要求。如果更改blah字段,則哈希碼將會更改。

+0

它的工作原理,但如果我不會重載hashCode(),可狀態變化影響返回值(哈希碼)? – zeds 2014-11-22 14:00:32

+0

如果繼承'Object.hashCode()',那麼狀態更改不會影響返回值,因爲返回值僅基於內存中的位置。如果它擴展了一些覆蓋'.hashCode()'的類,那麼它將取決於該類正在做什麼。 – 2014-11-22 14:06:14

+0

原來使用Object.hashCode()更好?爲什麼我們需要在這種情況下重寫hashcode()? – zeds 2014-11-22 14:18:22

1

如果您使用下面的類的對象在一個HashMap,並調用的setState雖然它在地圖上,你將有問題。

Class MutableExample { 
    private int state; 

    public void setState(int s) { 
     state = s; 
    } 

    public int hashCode() { 
     return state; 
    } 

    public boolean equals(Object o) { 
     if (!(o instanceof MutableExample)) { 
      return false; 
     } 

     return ((MutableExample) o).state == state; 
    } 
} 
0
假設

Person是可變的,並且hashCodeequals基於兩個屬性計算 - firstNamelastName

Person p1 = new Person ("John", "Smith"); 
Person p2 = new Person ("John", "Doe"); 
Set<Person> persons = new HashSet<Person>(); 
persons.add (p1); 
System.out.println(persons.contains(p2)); // prints false 
p2.setLastName("Smith"); 
System.out.println(persons.contains(p2)); // prints true 

更糟糕:

Person p1 = new Person ("John", "Smith"); 
Person p2 = new Person ("John", "Doe"); 
Set<Person> persons = new HashSet<Person>(); 
persons.add (p1); 
System.out.println(persons.contains(p2)); // prints false 
persons.add (p2); 
p2.setLastName("Smith"); 
System.out.println(persons.size()); // prints 2 
System.out.println(p1.equals(p2)); // prints true 

HashSet被打破 - 它含有兩個相同的實例。

同樣的例子適用於HashMap s,其中關鍵是Person