HashMap不添加重复键

时间:2014-03-25 19:48:02

标签: java collections hashmap scjp

import java.util.*;

class U {
    int x;

    U(int x) {
        this.x = x;
    }
}

public class G {
    public U a = new U(22);
    public U b = new U(23);
    Integer y = 22;
    Integer r = 23;

    void a() {
        Map<U, Integer> set = new HashMap<U, Integer>();
        set.put(a, y);
        set.put(a, r);
        set.put(b, y);
        System.out.print(set.size() + " ");
    }

    public static void main(String[] args) {
        G m = new G();
        m.a();
    }
}

我总是对地图和列表感到困惑。 我知道当map将密钥放入集合时,它会调用hashcode,如果存储桶相同,则调用equal方法。但是,我了解到如果类覆盖这两种方法,则不会存储重复的键。例如包装类:String实现自己的hashcode和equal方法。此外,如果您不这样做,则会调用唯一的哈希码,并将重复的密钥存储在集合中。

但是在上面的例子中,类U没有实现hashcode和equal方法。但是,Map不允许重复键。

我检查了SIZE:它的2 它应该是3,因为我的U类没有实现hashcode也不等。

请告诉我

提前致谢

4 个答案:

答案 0 :(得分:7)

HashMap不允许重复的密钥

如果您没有提供hashcode()equals()来自超级类的extends(对于您的情况,它是java.lang.Object),并且该实现提供了相同对象的相同哈希码和同一对象上的equals()返回true

public boolean equals(Object obj) {
    return (this == obj);
}

以及

答案 1 :(得分:1)

您使用U的同一个实例作为密钥两次:

set.put(a, y);
set.put(a, r);

你提到的U类没有实现hashCode(),所以默认实现是Object#hashCode,它显然是相同的,因为它是同一个实例。因此,地图将仅包含第二个条目。但是,如果您尝试以下操作,最终会有两个单独的条目:

set.put(new U(22), y);
set.put(new U(22), r);

但一般情况下,您始终希望为用作地图键的任何类实施equals()hashCode() - 否则您无法查看该值而无法访问实例它存储为!

答案 2 :(得分:0)

通过设计哈希映射不添加重复键。它将使用该键替换映射中当前项的值。见http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29

答案 3 :(得分:0)

如果您想添加重复的密钥,请尝试以下方法:

    Map<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();

    map.put(1, new ArrayList<Integer>());
    map.get(1).add(1);
    map.get(1).add(2);