对象如何存储在 HashMap 中? [复制]

Posted

技术标签:

【中文标题】对象如何存储在 HashMap 中? [复制]【英文标题】:How the objects are stored in HashMap? [duplicate] 【发布时间】:2019-01-28 21:01:21 【问题描述】:

我对下面的代码感到困惑。当我更改员工 e2 的名称时,我希望地图同时具有 e2 和 e3 对象,因为 e2 对象现在与 e3 不同。但似乎更改 e2 对象的名称并未反映在存储在 hashmap 中的 e2 对象中,因此输出仅显示 e3。所以我很困惑哈希图是存储实际对象还是仅存储原始对象的副本。

代码:

import java.util.HashMap;

public class Main 

    public static void main(String[] args) 

        HashMap<Employee,Integer> map = new HashMap<Employee,Integer>();

        Employee e1 = new Employee(10,"Sachin");
        Employee e2 = new Employee(10,"Sachin");

        map.put(e1, 1);
        map.put(e2,2);

        System.out.println(e1.hashCode()+"    "+e2.hashCode());

        System.out.println(map);

        e2.setName("Akshay"); //<---- changing the name for e2

        Employee e3 = new Employee(10,"Sachin");        
        map.put(e3, 3);

        System.out.println(map);
    


class Employee

    private int id;
    private String name;

    public Employee(int id, String name) 
        super();
        this.id = id;
        this.name = name;
    

    public int getId() 
        return id;
    
    public void setId(int id) 
        this.id = id;
    
    public String getName() 
        return name;
    
    public void setName(String name) 
        this.name = name;
    

    @Override
    public int hashCode() 
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    

    @Override
    public boolean equals(Object obj) 
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee other = (Employee) obj;
        if (id != other.id)
            return false;
        if (name == null) 
            if (other.name != null)
                return false;
         else if (!name.equals(other.name))
            return false;
        return true;
       

输出:

-1826112337    -1826112337
Employee [id=10, name=Sachin]=2
Employee [id=10, name=Sachin]=3

【问题讨论】:

当您尝试为现有键放置值时,只会替换关联的值。所以你的put(e2, 2) 不会取代e1 作为键。 所以 e1 在 hashmap 中永远不会被替换,而只是考虑到相同的 key 值被更新为 2 。所以 e2 从来没有添加到 hashmap 中,当我做 put(e3,3) 时,同样的事情发生了 e3 没有被添加,只是值被更新为 3 没错。添加另一个未在哈希码或 equals 中使用但仅用于日志记录的 id 可能会有所帮助。 【参考方案1】:

您可能知道,HashMap 中的每个条目都根据其 hashCode() 分配一个存储桶。当条目在 Map 中 put() 时分配存储桶(将项目添加到 HashSet 也是如此)

如果您在放入 Map 后对键进行了变异,则 HashMap 不知道该变异。它不会重新计算存储桶并将条目移动到新存储桶(怎么可能?它无法监听此事件)

根据经验,不要改变 Map 中的键(或 Set 中的项),因为 Map.containsKey(...) 和 Set.contains(... ) 等。

【讨论】:

好的,所以存储在条目中的密钥对象与实际的密钥对象不同?因为我正在改变关键对象,所以如果两个对象相同或指向相同的内存位置,也不应该反映在存储在 hashmap 中的关键对象中? 这是对 的错误解释,但似乎更改 e2 对象的名称并未反映在存储在 hashmap 中的 e2 对象中,因此输出仅显示 e3。 查看我的更新,只有在添加条目时才分配存储桶。如果您随后更改密钥的 hashCode() 您将得到意外的行为,因为密钥不再与存储桶匹配 他们不会改变HashMap 中的任何键。 e2 引用的对象从未出现在其中。 嗯……显然是看错了代码

以上是关于对象如何存储在 HashMap 中? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何将字符串类型的数组值存储到HashMap对象中

如何测量数据结构的内存使用情况? [复制]

如何在HashMap中存储一个带Gson的JSON

数据结构之散列链表(Java语言描述)

如何在 Wildfly Standalone-full-ha 中使用复制的 Infinispan 缓存

可以总结HashMap中的对象值吗? [复制]