2015-09-29 76 views
3

重寫equals() and hashCode()對於TreeMap不是必需的,同時需要HashMapLinkedHashMapJava中的equals()和hashCode()LinkedHashMap和樹形圖?

TreeMap工程實施上使用用戶創建的類作爲KeyMap

這是正確的ComparableComparatorinterface提供?

+0

你是對的 – Eran

+0

你的第二個陳述是錯誤的。 'TreeMap'也應該服從Map的一般合約,然後在它之上,Comparable和Comparator來。 –

+0

但是當試圖調試程序代碼....它永遠不會進入equals()方法....試圖實現碰撞條件以及..通過每次返回相同的int值...沒有它的情況下達到等於()。 – user3571396

回答

1

內部TreeMap只能使用compare函數的鍵。

方法containsValue內部使用equals。所以有必要重新定義equals的值,而不是鍵。

HashMapLinkedHashMap在鍵上內部使用equalshashCode。所以你需要爲你的關鍵類重新定義它。至於TreeMap,HashMapLinkedHashMap使用equals作爲值。所以有必要重新定義值的等於。

0

是的,我是正確的(請糾正我,如果我錯了)...查看下面的代碼 -

In this following code `equals()` and `hashCode()` is never get called , so in `TreeMap` does these never gets called in `TreeMap` ?? Or something wrong I have Done ???? its never printing `inside hashCode()` `inside equals()` 

package Map; 

import java.util.HashMap; 
import java.util.Map; 
import java.util.TreeMap; 

public class HashCodeEqualsTester { 

    public static void main (String[] args){ 

     Car car1 = new Car("788"); 
     Driver driver1 = new Driver("Kevin"); 

     Car car2 = new Car("656"); 
     Driver driver2 = new Driver("Bob"); 

     Car car3 = new Car("343"); 
     Driver driver3 = new Driver("Stuart"); 

     Map<Car, Driver> myMap = new TreeMap<Car, Driver>(); 
     // Map<Car, Driver> myMap = new LinkedHashMap<Car, Driver>(); 
     // Map<Car, Driver> myMap = new HashMap<Car, Driver>(); 
     // try to run these 3 one at a time and see how does it behave 

     myMap.put(car1, driver1); 
     myMap.put(car2, driver2); 
     myMap.put(car3, driver3); 



     System.out.println(myMap); 
    } 
} 

class Car implements Comparable{ 
    private String carNumber; 

    public Car (String carNumber){ 
     this.carNumber = carNumber; 
    } 
    public String getCarNumber() { 
     return carNumber; 
    } 
    public void setCarNumber(String carNumber) { 
     this.carNumber = carNumber; 
    } 
    public String toString(){ 
     return ("Car Number : " + carNumber); 
    } 

    public int hashCode(){ 
     System.out.println("Inside hashCode()"); 
     int hashCode = 1; 
     hashCode = hashCode * this.getCarNumber().hashCode(); 
     System.out.println("For Car Number : " + this.getCarNumber() + " hashcode is : " + hashCode); 
     //return hashCode; 
     return 1000; 
    } 

    public boolean equals(Object o){ 
     System.out.println("Inside equals()"); 
     if (!(o instanceof Car)) { 
      return false; 
     } else { 
      Car car = (Car) o; 
      return (this.getCarNumber().equalsIgnoreCase(car.getCarNumber())); 
     } 
    } 

    public int compareTo(Object o) { 
     Car car = (Car) o; 

     return (this.getCarNumber().compareTo(car.getCarNumber())); 
    } 
} 

class Driver { 
    private String name; 

    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 
    public String toString(){ 
     return (this.getName() + " "); 
    } 
    public Driver(String name){ 
     this.name = name; 
    } 
} 
1

要回答這樣的問題,它更更好的閱讀文檔,而不是進行測試。測試沒有顯示。即使您看到這些方法未被調用,但這並不意味着它們不會在更多的Java版本或另一個JDK供應商中被調用。或者可能在您的地圖上執行其他一些操作時可能會調用這些方法。

在這種特殊情況下,documentation說以下內容:

注意,排序由一棵樹映射維護,像任何排序的映射,無論是否提供了明確的比較,必須一致equals如果這個排序圖是要正確實現Map接口。 (對於一致的精確定義與equals參見ComparableComparator)。這是因爲該Map接口在equals操作定義的,而是一個排序映射使用它compareTo(或compare)方法所有的鍵比較,於是兩個從排序映射的角度來看,這種方法認爲相同的密鑰是相等的。即使其排序與equals不一致,排序映射的行爲也是;它只是不服從Map接口的總體合同。

強調我的。

因此,根據最後一句話,如果您沒有定義密鑰的equals方法,TreeMap將完全正常工作,但它會違反Map接口的合同。例如,Map.containsKey合同如下:

返回true如果此映射包含指定鍵的映射。更正式地,返回true當且僅當該映射包含關鍵字k的映射,例如(key==null ? k==null : key.equals(k))

因此,如果您使用TreeMap鍵與equals實現不一致,這將是錯誤的。如果您將地圖傳遞給某種假定傳遞的地圖符合合同的方法,則該方法可能會錯誤地工作。

1

我總是遵循一個簡單的配方:對於所有的地圖實現,我總是覆蓋hashCode()equals()。如果地圖也是SortedMap,我也覆蓋compare()或執行Comparator(在兩種情況下,比較必須與equals()一致,這意味着如果比較的元素實際上相等,則比較結果必須返回0)。

這個配方允許我使用任何地圖實現,我覺得最適合我正在處理的特定問題,它甚至允許我爲同一個關鍵類使用不同的地圖實現。