2013-05-29 117 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

'的hashCode()'和'等于()'实现失踪。 –

回答

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方法检查。您可以看到在插入之前,此方法同时检查了hashcodeequality。所以如果你不重写这些方法,它将使用超类的(对象的)方法,它将为不同的对象返回不同的值。因此,虽然对于相同的键,两个值将被插入分开的地方Hashmap。所以你需要重写这两个,并确保对于两个相同的对象,你应该返回相同的hashcode

代码

所以,你的敏应该是这样

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; 
    } 
}