4

今天面试,得到如下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

4

7 回答 7

12

您的问题是,equals()并且hashcode()没有在MyInt.

在这两种情况下,您都应该得到2结果。

HashMap,顾名思义,根据键的hashcode()将键分组到中。但是对于具有相同值的两个实例,默认哈希码不匹配。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;
    }

}
于 2013-05-29T16:33:50.833 回答
3

你需要重写你的类中的equals()andhashCode()方法MyInt,这样HashMap才能理解new MyInt(1).equals(new MyInt(1))is true

于 2013-05-29T16:33:43.507 回答
2

Integer 类覆盖了equals()进行基于值比较的方法。Hashmaps 不能包含两个“相等”的键,因此第二次插入 map1 将覆盖第一个条目。同样,该hashcode()方法被覆盖。

但是,MyInt 不会覆盖equals()orhashcode()方法,因此相等是基于内存位置的。因此,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(one) 在这种情况下为真。

于 2013-05-29T16:34:42.497 回答
1
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());

    }

此代码将打印;

3 3

因此,您的 Integer 类(myInt)是真实的,但缺少

于 2013-05-29T16:47:09.313 回答
1

Integer 类重写 equals() 方法进行基于值的比较。无需手动包含 equals() 或 hashcode() 方法。我的解决方案如下

import java.util.HashMap;
import java.util.Map;

    public class HashMapEqualsHashcode {

        public static void main(String[] args) {

            MyInt obj = new MyInt(50);

            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 "+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 "+map2.size());
        }
    }

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



    }

解决方案的屏幕截图

https://i.stack.imgur.com/yVkgL.png

于 2020-06-01T12:49:08.623 回答
0

您必须覆盖hashCode()andequals方法。对于两个对象的 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;
    }
}
于 2013-05-29T16:54:29.773 回答
0

Integer 类覆盖 equals() 方法以进行基于值的比较。Hashmaps 不能包含两个“相等”的键,因此第二次插入 map1 将覆盖第一个条目。同样,hashcode() 方法也被覆盖。

但是,Myint 不会覆盖 equals() 或 hashcode() 方法,因此相等是基于内存位置的。因此,map2 看到三个不同的键并生成三个不同的条目。

于 2020-05-30T10:55:53.477 回答