Почему этот HashMap.get возвращает ноль? - PullRequest
5 голосов
/ 21 мая 2011

Я пытаюсь создать Hashmap, чтобы выполнить поиск для меня.Однако, когда я запускаю этот тестовый код, вывод будет нулевым.Я думаю, что это связано с характером хранения ключей, но я не уверен.Возможно, это похоже на причуду, например, что var1 == var2 не равны, если они не указывают на один и тот же объект в памяти, вместо этого вы должны использовать var1.equals(var2)?

. Есть два класса для проверки этого.

TestCard.java

import java.util.HashMap;

public class TestCard {

     // HashMap for SpecialK Lookup
    private static HashMap<Card, Integer> specialKLookup = new HashMap<Card, Integer>();

    // Constructor
    public TestCard(){
    }

    public static void main(String[] args) {
        Card[] cards = new Card[3];
        cards[0] = new Card((short)12, (short)0);
        cards[1] = new Card((short)0, (short)1);
        cards[2] = new Card((short)5, (short)2);

        /* Build SpecialK Lookup HashMap.
         * Ace of Spades = 0
         * Ace of Hearts = 1
         * Ace of Diamonds = 2
         * Ace of Clubs = 3
         * ...
         * Two of Clubs = 51
         */
        Integer specialKCounter = 0;
        for(int i=12;i>=0;i--){
                for (int j=0;j<4;j++){
                        specialKLookup.put(new Card((short)i, (short)j), specialKCounter++);
                }
        }

        System.out.println(specialKLookup.get(cards[0]));
    }
}

Card.java

public class Card{
    private short rank, suit;

    private static String[] ranks = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"};
    private static String[] suits = {"Spades", "Hearts", "Diamonds", "Clubs"};

    //Constructor
    public Card(short rank, short suit){
        this.rank = rank;
        this.suit = suit;
    }

    // Getter and Setters
    public short getSuit(){
        return suit;
    }

    public short getRank(){
        return rank;
    }

    protected void setSuit(short suit){
        this.suit = suit;
    }

    protected void setRank(short rank){
        this.rank = rank;
    }   
}

Ответы [ 6 ]

13 голосов
/ 21 мая 2011

В классе (Card) отсутствует правильная реализация equals(Object) и hashCode()

Без обоих этих определений просто не будет работать . (Он прекрасно компилируется, потому что эти методы являются как виртуальными, так и наследуемыми во всех объектах, поскольку они являются частью Object: HashMap не может применить это во время компиляции.) См. Ссылки выше для необходимого контракта.

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

Если эти методы не перегружены, то используются реализации, определенные в Object. То есть x.equals(y) имеет семантику, близкую к x == y, а hashCode возвращает стабильное число для контракта. Это эффективно заставляет карту работать как карта идентификации (когда объекты Card являются ключами): только точно такой же объект может извлечь ранее сохраненное значение - каждый другой get вернет null, как наблюдалось.

Счастливого кодирования.

3 голосов
/ 21 мая 2011

Это действительно именно из-за этой проблемы.

Вам необходимо определить, что означает равенство на карточках, поэтому вам необходимо переопределить методы equals и hashCode.

Если вы этого не сделаете, то предполагается, что две карты равны, только если они одного и того же экземпляра. (Как и в поведении по умолчанию equals.)

Обратите внимание, что очень важно, чтобы вы переопределяли equals и hashCode, так как два объекта, равные , должны хешироваться в одно и то же значение, чтобы HashMap работал правильно.

Для получения дополнительной информации см. Переопределение equals и hashCode в Java .

2 голосов
/ 21 мая 2011

Возможно, это аналогично быстрому тому, что var1 == var2 не равны, если они не указывают на> тот же объект в памяти, вместо этого вы должны использовать var1.equals (var2)

Почти.Как и следовало ожидать, хэш-карте нужен способ получения хеш-кодов для ваших объектов.В Java это обеспечивается методом hashCode , который реализован Object, но должен быть переопределен вашим классом Card.

* update: как указывает pst, он также должен переопределитьравно.

1 голос
/ 21 мая 2011

Вам придется переопределить метод hashCode() для Card и заставить его возвращать то же значение, если и только если карты равны - вы должны также переопределить equals().Потому что это то, на что опирается HashMap, чтобы найти объекты, на которые ссылаются ключи;В настоящее время используются версии тех методов, унаследованных от Object, которые будут совпадать только в том случае, если вы используете те же объекты, что и ключи, тогда как вы создаете новые, хотя и «равные», единицы.

1 голос
/ 21 мая 2011

Карта должна переопределить equals и hashCode.Взгляните сюда: http://www.ibm.com/developerworks/java/library/j-jtp05273/index.html

1 голос
/ 21 мая 2011

Вам необходимо реализовать методы hashCode и equals, так как это позволяет проверять равенство двух разных объектов, а также помогает с хранением карты хеша. Без их реализации два объекта будут рассматриваться как отдельные, даже если их свойства одинаковы. Подробнее см. http://www.jchq.net/certkey/0902certkey.htm.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...