zoukankan      html  css  js  c++  java
  • java HashMap插入重复Key值问题

    要在HashMap中插入重复的值,首先需要弄清楚HashMap里面是怎么存放元素的。
    put方法
    Map里面存放的每一个元素都是key-value这样的键值对,而且都是通过put方法进行添加的,而且相同的key在Map中只会有一个与之关联的value存在。put方法在Map中的定义如下。

    V put(K key, V value);
    1
    put()方法实现:首先hash(key)得到key的hashcode(),hashmap根据获得的hashcode找到要插入的位置所在的链,在这个链里面放的都是hashcode相同的Entry键值对,在找到这个链之后,会通过equals()方法判断是否已经存在要插入的键值对,而这个equals比较的其实就是key。

    它用来存放key-value这样的一个键值对,返回值是key在Map中存放的旧value,如果之前不存在则返回null。HashMap的put方法是这样实现的。

    // 在此映射中关联指定值与指定键。如果该映射以前包含了一个该键的映射关系,则旧值被替换
    public V put(K key, V value) {
    // 当key为null,调用putForNullKey方法,保存null与table第一个位置中,这是HashMap允许为null的原因
    if (key == null)
    return putForNullKey(value);
    // 使用hash函数预处理hashCode,计算key的hash值
    int hash = hash(key.hashCode());//-------(1)
    // 计算key hash 值在 table 数组中的位置
    int i = indexFor(hash, table.length);//------(2)
    // 从i出开始迭代 e,找到 key 保存的位置
    for (Entry<K, V> e = table[i]; e != null; e = e.next) {
    Object k;
    // 判断该条链上是否有hash值相同的(key相同)
    // 若存在相同,则直接覆盖value,返回旧value
    if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
    // 旧值 = 新值
    V oldValue = e.value;
    // 将要存储的value存进去
    e.value = value;
    e.recordAccess(this);
    // 返回旧的value
    return oldValue;
    }
    }
    // 修改次数增加1
    modCount++;
    // 将key、value添加至i位置处
    addEntry(hash, key, value, i);
    return null;
    }

    从上我们可以看到在添加对应的key-value这样的组合时,如果原本已经存在对应的key,则直接改变对应的value,并返回旧的value,而在判断key是否存在的时候是先比较key的hashCode,再比较相等或equals的。
    直接从上面代码来看是比较的对应Map.Entry的hashCode和key的hashCode,而实际上Map.Entry的hashCode其实就是其存放key的hashCode。而如果对应的key原本不存在的话将调用addEntry将对应的key-value添加到Map中。addEntry传递的参数hash就是对应key的hashCode。
    实现引用对象作为keys的唯一性
    通过对put()方法的研究,我们可以发现,判断key是否存在的时候是先比较key的hashCode,再比较相等或equals的,所以重写hashCode()和equals()方法即可实现覆盖keys的引用(指向具有相同实例变量的对象)。

    class MyType {
    private String arga;
    private String argb;

    public MyType(String arga, String argb) {
    this.arga = arga;
    this.argb = argb;
    }

    @Override
    public int hashCode(){
    return this.arga.hashCode() * this.argb.hashCode() ;
    }

    @Override
    public boolean equals(Object obj) {
    if (this == obj) {
    return true;
    }
    if (!(obj instanceof MyType)) {
    return false;
    }
    MyType p = (MyType) obj;
    if (this.arga.equals(p.arga) && this.argb.equals(p.argb)) {
    return true ;
    } else {
    return false ;
    }
    }
    }

    重写这两个方法之后就可以覆盖重复的引用对象,如果需要对value进行叠加,调用put()方法之前用containsKey()方法判断是否有重复的键值,如果有,则用get()方法获取原有的value,再加上新加入的value即可。

    文章参考自:https://my.oschina.net/elim1/blog/811867
    http://blog.csdn.net/dajian790626/article/details/13628137

    版权声明:本文为CSDN博主「山木枝」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/intersting/article/details/72627353

  • 相关阅读:
    latex之插入伪代码 [转]
    BIBTeX制作参考文献 [转]
    latex 页眉设置 [转]
    python : list tuple set dictionary [转]
    ctags使用简介 [转]
    conda在指定目录下创建虚拟环境
    Ubuntu系统安装Anaconda3
    ModuleNotFoundError: No module named 'google' 问题解决方案
    PyCharm无法输入中文
    checkpoint文件
  • 原文地址:https://www.cnblogs.com/chaojibaidu/p/12614350.html
Copyright © 2011-2022 走看看