2013-05-29 2 views
2

у меня было интервью сегодня, и я получил следующий Java-код:HashMap в Java

public class Question_6 { 
    public static void main(String[] args){ 
     Map<Integer,String> map1 = new HashMap<Integer,String>(); 
     map1.put(new Integer(1),"001a"); 
     map1.put(new Integer(1),"001b"); 
     map1.put(new Integer(2),"002"); 

     System.out.println(map1.size()); 

     Map<MyInt,String> map2 = new HashMap<MyInt,String>(); 
     map2.put(new MyInt(1),"001a"); 
     map2.put(new MyInt(1),"001b"); 
     map2.put(new MyInt(2),"002"); 

     System.out.println(map2.size()); 

    } 

} 
public class MyInt { 
    int i; 
    public MyInt(int i) { 
     this.i = i; 
    } 

} 

Вопросы были:

  1. Что будет распечатана на консоль?

  2. Предложить решение проблемы.

теперь я знаю, что ответ на первый вопрос:

2 

3 

Но я не знаю, почему? В чем проблема с MyInt?

+3

'хэш-код()' и 'Equals()' реализации отсутствуют. –

ответ

10

Ваша проблема заключается в том, что equals() и hashcode() не реализованы на MyInt.

Ожидается, что в обоих случаях ожидается 2.

HashMap, как следует из названия, группы ключей в ведер на основе ключей хэш-код(). Но хэш-код по умолчанию не подходит для двух экземпляров MyInt с тем же значением.

Чтобы определить равенство, вам необходимо переопределить equals().

Одно из решений:

public class MyInt { 

    [...] 

    @Override 
    public int hashCode() { 
     return value; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj instanceof MyInt) { 
      return i == ((MyInt)obj).i; 
     } 
     return false; 
    } 

} 
+0

Большое спасибо. Я думал, что только переопределения hashcode() будет достаточно, и я забыл о equals(). – Moosh

3

Вы должны переопределить equals() и hashCode() метод в MyInt классе, так что HashMap может понять new MyInt(1).equals(new MyInt(1)) является true.

1

Класс Integer перекрывает equals() способ сделать сравнение на основе стоимости. Хашмапы не могут содержать две клавиши, которые являются «равными», поэтому вторая вставка в map1 перезапишет первую запись. Кроме того, метод hashcode() переопределяется.

Однако MyInt не переопределяет метод equals() или hashcode(), поэтому равенство основано на памяти. Поэтому map2 видит три разных ключа и делает три разных записи.

Map<MyInt,String> map2 = new HashMap<MyInt,String>(); 
    MyInt one = new MyInt(1); 
    MyInt two = new MyInt(2); 
    map2.put(one,"001a"); 
    map2.put(one,"001b"); 
    map2.put(two,"002"); 

    System.out.println(map2.size()); 

производит выход 2 в этом случае, поскольку one.equals (один) верно в этом случае.

0
map1.put(new Integer(1),"001a"); 
     map1.put(new Integer(1),"001b");//same location in map 
     map1.put(new Integer(2),"002"); 

в этой части вы используете класс Integer, Integer класс не позволяет установить в том же месте, но ваш класс Integer позволяет.

Изменить код, как это, и вы видите проблему

public class Question_6 { 
    public static void main(String[] args){ 
     Map<Integer,String> map1 = new HashMap<Integer,String>(); 
     map1.put(new Integer(1),"001a"); 
     map1.put(new Integer(2),"001b"); 
     map1.put(new Integer(3),"002"); 

     System.out.println(map1.size()); 

     Map<MyInt,String> map2 = new HashMap<MyInt,String>(); 
     map2.put(new MyInt(1),"001a"); 
     map2.put(new MyInt(2),"001b"); 
     map2.put(new MyInt(3),"002"); 

     System.out.println(map2.size()); 

    } 

этот код будет печатать;

Итак, ваш класс Integer (Минт) истинно, но отсутствует

0

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

Почему?

если вы проверите в исходном коде HashMap.put метод. вы можете видеть, что этот метод проверяет как hashcode, так и equality перед вставкой. Поэтому, если вы не переопределите эти методы, он будет использовать методы суперкласса (объекта), которые возвратят разные значения для разных объектов. Таким образом, хотя для одного и того же ключа два значения будут вставлены в отдельное место Hashmap. Поэтому вам нужно переопределить эти два и убедиться, что для двух равных объектов вы должны вернуть одинаковые hashcode.

Код

Так что ваш MyInt должно быть что-то вроде

public class MyInt { 
    int i; 
    public MyInt(int i) { 
     this.i = i; 
    }   

    public int hashCode() { 
     return i; 
    }  

    public boolean equals(Object obj) { 
     if (obj instanceof MyInt && i == ((MyInt)obj).i) { 
      return true; 
     } else 
      return false; 
    } 
}