2015-09-29 8 views
3

переопределение equals() and hashCode() не требуется для TreeMap, если требуется для HashMap и LinkedHashMap.equals() и hashCode() в Java LinkedHashMap и древовидная карта?

TreeMap работа по реализации, предоставляемая Comparable или Comparatorinterface при использовании созданного пользователя Классов как Key для Map

Правильно ли это?

+0

Вы правы – Eran

+0

Ваше второе утверждение неверно. 'TreeMap' также должен подчиняться генеральному контракту Map, а затем поверх него, приходит Comparable и Comparator. –

+0

, но при попытке отладки кода программы .... Его никогда не происходит внутри метода equals() .... Пытался достичь условия столкновения, а также ... возвращая одинаковое значение int каждый раз ... ни один из случаев его достижения to equals(). – user3571396

ответ

1

Внутренний TreeMap использование только compare функция для ключей.

Способ containsValue использование внутри equals. Поэтому для значений, но не для ключей, необходимо переопределить equals.

HashMap и LinkedHashMap использование внутри и hashCode на ключах. Поэтому вам нужно переопределить его для своего ключевого класса. Что касается TreeMap, также HashMap и LinkedHashMap использует значения 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. (См Comparable или Comparator для точного определения в соответствии с equals.) Это так, потому что интерфейс Map определен в терминах equals операции, но отсортированная карта выполняет все ключевые сравнения, используя свой метод compareTo (или compare), так что два ключи, которые считаются равными по этому методу, равны, с точки зрения сортированной карты. Поведение сортированной карты равно, четкое, даже если его порядок не соответствует equals; он просто не подчиняется генеральному контракту интерфейса Map.

Emphasis mine.

Так, согласно последней предложении TreeMap будет полностью функциональным, если вы не определить метод equals для ключей, но это нарушит договор интерфейса Map.Например, Map.containsKey контракт заключается в следующем:

Возвращает true если эта карта содержит отображение для указанного ключа. Более формально возвращает true тогда и только тогда, когда эта карта содержит отображение для ключа k такого, что (key==null ? k==null : key.equals(k)).

Так что это было бы неправильно, если вы используете TreeMap с ключами, имеющих противоречивый equals реализации. Если вы передадите карту на какой-то метод, предполагающий, что переданная карта соответствует контракту, тогда этот метод может работать некорректно.

1

Я всегда придерживаюсь простого рецепта: для всех реализаций карт я всегда переопределяю hashCode() и equals(). Если карта также является SortedMap, я также переопределяю compare() или реализую Comparator (в обоих случаях сравнение должно соответствовать equals(), что означает, что результат сравнения должен возвращать 0, если сравниваемые элементы на самом деле равны).

Этот рецепт позволяет мне использовать любую реализацию карты, которую я считаю наиболее подходящей для конкретной проблемы, которую я решаю, и даже позволяет мне использовать разные реализации карт для одного и того же ключевого класса.