2015-07-01 1 views
2

Это простой вопрос о java.HashMap способ делать содержитKey не ведет себя как ожидалось

Сегодня я занимался поиском пути, когда мне пришлось использовать , чтобы найти класс Coord в другом keySet() от Coord. Я обнаружил, что когда я использовал готовый метод containsKey(), он просто не работал так, как я хотел. Я сделал тест, чтобы выяснить, что происходит и здесь:

HashMap<Coord, Coord> test = new HashMap<Coord, Coord>(); 
test.put(new Coord(3, 3), new Coord(0, 0)); 

System.out.println("HashMap test for containsKey : " + test.containsKey(new Coord(3, 3))); 

boolean containsKey = false; 
for(Coord a : test.keySet()) 
{ 
    if(a.equals(new Coord(3, 3))) 
    { 
     containsKey = true; 
    } 
} 

System.out.println("My test for containsKey : "+containsKey); 

И удивительно, вот что я нашел:

HashMap test for containsKey : false 
My test for containsKey : true 

Я просто хотел бы знать, что происходит и почему.

Кроме того, здесь есть Coord класс:

public class Coord 
{ 
    public float x, y; 

    public Coord(float a, float b) 
    { 
     this.x = a; 
     this.y = b; 
    } 

    @Override 
    public boolean equals(Object b) 
    { 
     if(b instanceof Coord) 
     { 
      Coord casted = (Coord) b; 
      return casted.x == x && casted.y == y; 
     } 
     return false; 
    } 
} 
+0

Прежде всего вы проверяете метод 'equals()'. вы не переопределили метод hashCode(). а также вы можете проверить код метода 'containsKey()'. он делает гораздо больше, чем вы ожидаете. Вы должны переопределить метод hashCode()! – Prashant

+0

Ну, я просто посмотрел на него и сделал третий тест с помощью простого test.get (new Coord (3, 3))! = Null ... И он вернул false. Я смотрю на код, чтобы понять, почему. –

+0

лучше вы можете проверить 'final Entry метод getEntry (Object key)'. – Prashant

ответ

6

HashMap s найти объекты по их хэш-код. Часть контракта заключается в том, что ключевой класс должен переопределить hashCode(), а также equals(). Хэш-коды по умолчанию для отдельных объектов не равны, поэтому объект не найден get. Напротив, когда вы перебираете все записи, хеш-код не используется, поэтому вызывается только equals, и объект найден.

Чтобы найти его, используя get, переопределить hashCode в Coord.

Всегда полезно переопределять hashCode всякий раз, когда вы переопределяете equals и наоборот.

0

Hashmap действительно работает на принципале hashing. Для правильных & ожидаемых результатов ключ, используемый в Hashmap, должен переопределить equals(), а также hashCode().

Так выше в то время как вы делаете test.containsKey(new Coord(3, 3)) вы создаете новый объект Coord поэтому его хэш-код отличается от Object который вы поставили ему карту, как его вызов Object класса hasCode() по умолчанию. Так containsKey() давая false

Но в то время как вы делаете a.equals(new Coord(3, 3)) вы вызываете перекрываться equals() который удовлетворяющее условия вы клали в вашем переопределенном методе, который в настоящее время удовлетворяется как Coord объектов, так давая выход в true.

Для правильных результатов также верно следует использовать hashCode().

Чтобы узнать больше о том, как HashMap работает на Java, вы можете стать в этом блоге here. Надеюсь, это помогло.

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