2014-09-10 2 views
0

Рассмотрим Ther следующий код:Маленький Путаница Над HASHING

public class CarEqualsTestAgain { 

String model; 

    public CarEqualsTestAgain(String x) { 
     this.model=x; 
    } 

    @Override 
    public int hashCode(){    //bad hashcode 
     System.out.println("__hash__"); 
     return 1; 
    } 

    @Override 
    public boolean equals(Object o){ 
     System.out.println("In equals"); 
     if((o instanceof CarEqualsTestAgain) && ((CarEqualsTestAgain)o).model==this.model){ 
      return true; 
     } 
     else 
      return false; 
    } 

    public static void main(String[] args) { 

     Map map=new HashMap(); 

     CarEqualsTestAgain car1=new CarEqualsTestAgain("8"); 
     map.put(car1, "Red"); 
     System.out.println("Key1 : "+map.get(car1));   //Line 1 

     CarEqualsTestAgain car2=new CarEqualsTestAgain("8"); 
     System.out.println("Key2 : "+map.get(car2));   //Line 2 

     CarEqualsTestAgain car3=car1; 
     System.out.println("Key3 : "+map.get(car3));   //Line 3 

     CarEqualsTestAgain car4=new CarEqualsTestAgain("9"); 
     map.put(car4, "Red"); 
     System.out.println("Key4 : "+map.get(car4));   //Line 4 

     CarEqualsTestAgain car5=new CarEqualsTestAgain("10"); 
     map.put(car5, "Red"); 
     System.out.println("Key5 : "+map.get(car5));   //Line 5 

     CarEqualsTestAgain car6=new CarEqualsTestAgain("8"); 
     map.put(car6, "Green"); 
     System.out.println("Key6 : "+map.get(car6));   //Line 6 

     key=(String)map.get(car1); 
     System.out.println("Key1 : "+key);     //Line 7 

    } 

} 

Отпечатки выход как:

__hash__ 
__hash__ 
Key1 : Red 

__hash__ 
In equals 
Key2 : Red 

__hash__ 
Key3 : Red 

__hash__ 
In equals 
__hash__ 
Key4 : Red 

__hash__ 
In equals 
In equals 
__hash__ 
Key5 : Red 

__hash__ 
In equals 
In equals 
In equals 
__hash__ 
In equals 
In equals 
In equals 
Key6 : Red 

__hash__ 
In equals 
In equals 
Key1 : Green 

Мой вопрос:

1) Когда каждый объект создается JVM вычислить его хэш-код и поместите его в ведро или когда вызывается метод Hashmap put(), тогда только JVM использует ключ Object для вычисления hashcode?

2) put() и get() вызывает как метод hashcode, так и equals. Следовательно, метод метода put() переопределяет equals() правильно в зависимости от no. объектов в ковше, как видно на выходе для линии 1,4,5,6. Но для метода get() это не одно и то же. Для строки 1 get() не вызывает равно(), строка 2 делала, строка 3,4,5 не вызывала, строка 6 делала. Линия 7 не ПОЧЕМУ?

3) метод equals (Object o) сравнивает пройденный объект i.e Object o со всеми объектами находится в ведре с заданным хэш-кодом. Тогда почему это не прекратило компиляцию, когда она обнаружила одну раннюю. Ex - Скажем в ковше 1928 car1 car4 car5, поэтому, когда car6 вызывает get(), который вызывает equals(), то если car6 сравнивается с car1 и считается равным, то он должен прекратить сравнивать, но вместо этого он сравнивается 3 раза. ЗАЧЕМ?

+0

Почему бы вам не взглянуть в исходный код? – stealthjong

+0

equals вызывается только в том случае, если ссылки не совпадают. то есть он сначала '=='. –

+0

@PeterLawrey, когда get() называется вызовом hashcode, после этого вызывается equals. Поэтому, когда происходит сравнение _ == _. – Nizam

ответ

1

При создании каждого объекта JVM вычислить его хэш-код и поместить его в ведро или Когда Hashmap ставить() метод вызывается только тогда JVM использует ключ объекта для вычисления хэш-код?

Это вызывает только hashCode(), когда это необходимо - в этом случае при вызове put() или get().

Для линии 1 get() не вызывает равную(), линия 2 сделала, линия 3,4,5 не вызывала, линия 6 сделала. Линия 7 не ПОЧЕМУ?

Вы сбиты с толку своей собственной диагностикой. Этот вызов:

System.out.println("Key1 : "+map.get(car1)); 

эквивалентно:

Object tmp = map.get(car1); 
System.out.println("Key1 : " + tmp); 

Так вызов equals происходит перед тем печати Key1. Чтобы было проще понять, вам следует изменить свою диагностику на:

System.out.println("Test 1"); 
CarEqualsTestAgain car1 = new CarEqualsTestAgain("8"); 
System.out.println("Created car"); 
map.put(car1, "Red");  
System.out.println("Added car to map"); 
Object tmp = map.get(car1); 
System.out.println("Result of get: " + tmp); 

Таким образом, становится яснее, что происходит, когда. В общем, как put() и get() необходимости:

  • Зов hashCode() на ключе вы добавляете/кокетливый
  • Если хэш-код спичек существующие в карте, вызовите equals() для каждого матча, пока она не будет бежит из матчей или находит равный объект

3) равно (метод объекта O) сравнивает принятый объект, т.е. объект о со всеми объектами находится в ведре с заданным хэшем-кодом.Тогда почему это не прекратило компиляцию, когда она обнаружила одну раннюю. Ex - Скажем в ковше 1928 car1 car4 car5, поэтому, когда car6 вызывает get(), который вызывает equals(), то если car6 сравнивается с car1 и считается равным, то он должен прекратить сравнивать, но вместо этого он сравнивается 3 раза. ЗАЧЕМ?

Вы считаете, что оно сначала сравнивается с car1. Карты хэшей фактически неупорядочены - нет никакой гарантии, что кандидаты с равными хеш-кодами будут сравниваться. Это будет остановится, когда найдет матч. Если вы измените свой хеш-код более разумным, очень вероятно, что ему нужно будет только проверить один элемент.

+0

Можете ли вы кратко рассказать о моей точке 3, как всякий раз, когда я запускал свою программу для получения (car6), я получил тот же результат для объекта car6, который равен три раза. Может ли существовать какая-либо возможность, что car6 сравнивает car1 и возвращает true перед сравнением любого другого объекта. Таким образом, можно назвать 1 раз. – Nizam

+0

@Nizam: В настоящее время ваш метод hashCode() 'возвращает 1 во всех случаях. Это делает его очень слабым хеш-кодом. Если вы вернете 'model.hashCode()' вместо этого, тогда он будет просматривать только автомобили, чья модель имеет тот же хэш-код. (Это не обязательно означает, что они равны, но это очень вероятно.) В будущем было бы полезно, если бы вы не добавили лишних бит в вопрос позже ... –

Смежные вопросы