当前位置: 首页 > 知识库问答 >
问题:

hashcode如何存储值

百里金林
2023-03-14

我有一节课

public class Customer {

    private int customerId;
    private String customerName;
    private String customerType;
    private String customerAddress;

    public Customer(int customerId, String customerName, String customerType, String customerAddress) {
        super();
        this.customerId = customerId;
        this.customerName = customerName;
        this.customerType = customerType;
        this.customerAddress = customerAddress;
    }

    public int getCustomerId() {
        return customerId;
    }

    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    public String getCustomerType() {
        return customerType;
    }

    public void setCustomerType(String customerType) {
        this.customerType = customerType;
    }

    public String getCustomerAddress() {
        return customerAddress;
    }

    public void setCustomerAddress(String customerAddress) {
        this.customerAddress = customerAddress;
    }

    @Override
    public String toString() {
        return "Customer [customerId=" + customerId + ", customerName=" + customerName + ", customerType="
                + customerType + ", customerAddress=" + customerAddress + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((customerAddress == null) ? 0 : customerAddress.hashCode());
        result = prime * result + ((customerName == null) ? 0 : customerName.hashCode());
        result = prime * result + ((customerType == null) ? 0 : customerType.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;
        Customer other = (Customer) obj;
        if (customerAddress == null) {
            if (other.customerAddress != null)
                return false;
        } else if (!customerAddress.equals(other.customerAddress))
            return false;
        if (customerName == null) {
            if (other.customerName != null)
                return false;
        } else if (!customerName.equals(other.customerName))
            return false;
        if (customerType == null) {
            if (other.customerType != null)
                return false;
        } else if (!customerType.equals(other.customerType))
            return false;
        return true;
    }

}

请注意,我已经从equal和hashcode计算中删除了customerId。我创建了这个方法来使用customer对象作为键

public static Map<Customer, String> testKeysWithObject(){
    Map<Customer, String> map = new HashMap<>();

    Customer customer1 = new Customer(1, "customerName1", "customerType1", "customerAddress1");
    Customer customer2 = new Customer(2, "customerName2", "customerType2", "customerAddress2");
    Customer customer3 = new Customer(3, "customerName3", "customerType3", "customerAddress3");
    Customer customer4 = new Customer(4, "customerName4", "customerType4", "customerAddress4");


    map.put(customer1, "customer1");
    map.put(customer2, "customer2");
    map.put(customer3, "customer3");
    map.put(customer4, "customer4");

    customer4 = new Customer(5, "customerName5", "customerType5", "customerAddress5");

    customer3.setCustomerAddress("customerAddress5");
    System.out.println(customer4.getCustomerAddress());
    return map;
}

下面是遍历Hashmap的方法。

public static void displayMap(Map<Customer, String> map) {
    System.out.println("==================================  ENTRY SET  ==========================================");
    for (Entry<Customer, String> mapKeys : map.entrySet()) {
        if(null != mapKeys)
            System.out.println("Key -> " + mapKeys.getKey() + " Value -> " + mapKeys.getValue()+ " HashCode -> " + mapKeys.hashCode());
    }
    System.out.println();
    System.out.println("==================================  KEY SET  ==========================================");
    for (Customer mapKeys : map.keySet()) {
        if(null != map.get(mapKeys))
            System.out.println("Key -> " + mapKeys + " Value -> " + map.get(mapKeys) + " HashCode -> " + map.get(mapKeys).hashCode());
    }
}

下面是输出。

customerAddress5

=========================================================================================================================================================键-

==================================================================================================================================================================键-

关于这个hashmap行为,我有几个问题

  1. 为什么hashmap不会受到Custer4=new赋值的影响,hashcode如何存储这些。
  2. hashmap是如何影响customer3.set客户地址(客户地址5);
  3. 为什么keyset()和entryset方法返回两个不同的值。
  4. hashmap是否存储实际对象的引用,如果引用,那么为什么客户4=new对hashmap没有影响?

共有3个答案

山越
2023-03-14

>

所有这些都是因为你的客户对象是Mutable.你可以参考这个和这个知道为什么HashMap键应该是不可变的。

这是因为customer3更改了Customer对象。设置CustomerAddress。检索Keyset()时,将返回所有键。但是,当您尝试使用该键检索值时,它现在将指向另一个bucket(请记住,您使用客户地址来计算hashcode)。

曾嘉祯
2023-03-14

您必须了解的是,您的四个Customer变量中的每一个都只是对某个对象的引用。当您调用map时。put(customer4,“customer4”),您的意思是“使用变量customer4引用的对象作为值“customer4”的键”。使用new语句重新指定customer4时,不会修改对象,而是更改customer4,使其不再引用第一个对象。

关于第二个问题,customer3同样是对变量的引用。指定customer3引用新的对象后,将该对象放入哈希映射中。现在有两个对这个对象的引用;其中一个是customer3,另一个是HashMap中的条目。调用setCustomerAddress()时,您现在正在对该对象进行操作,因此从这两个参考点都可以看到更改。

至于keyset()和entryset()方法返回differnethashCodes的原因,在第一个循环中,mapKeys的类型是Entry,而在第二个循环中,map。get(mapKeys)的类型是String,因此它们自然会生成不同的hashCodes。

最后,Java中的所有内容都是引用。当您将customer4放入地图时,您实际上是在放置对对象的引用。当您重新分配customer4时,您只是将一个变量指向另一个对象,但引用的另一个副本并没有消失。因此,更改变量customer4不会影响地图中的条目。

滕夜洛
2023-03-14

为什么hashmap不受customer4=新分配的影响,hashcode如何存储这些内容。

将新对象指定给customer4变量时,不会更改对象本身。映射保留对旧对象的引用,并且不知道您已经更改了customer4

hashmap是如何受customer3影响的。setCustomerAddress(“customerAddress5”);

您正在更改对象本身。两个客户3和客户在地图上指向同一个对象。

为什么keyset()和entryset方法返回两个不同的值。

永远不要把可变对象作为键。或者至少在放入地图后不要改变它们。地图无法处理此更改,也无法重新排序条目。这就是为什么带有"Custeraddres5"的键是"错过"的原因。

正如我所看到的变化反映在entryset()而不是keyset()中,这让我想知道hashmap如何能够用一种方法而不是另一种方法来弥补变化。

entrySet方法返回带有(键)的整个集合-

方法只返回键。它还返回4个项,但是您正在用"顾客地址5"过滤掉条目,因为您正试图通过这个键获取值。但是,此键的hashcode已经更改,因为您更改了地址字段,并且映射无法检索此键的值。

结论:永远不要更改密钥状态。让它不变,这样就没有人能改变它。

hashmap是否存储实际对象的引用,如果是引用,那么为什么customer4=new对hashmap没有影响?

您正在重新分配Custer4。再读一遍第一个问题的答案。

 类似资料:
  • 我正在学习firebase,有一些关于Firebase存储的问题: < li >我可以使用的总文件大小的限制? < li >我想使用firebase datastorage使用avatar上传图像,然后使用该url将图像加载到带有glide或picasso的imageview。可能吗? < li >我想将我的应用程序与firebase authenticate配合使用,以使用登录、firebase

  • 我正在尝试在谷歌云上迁移我的rails应用程序。我已将活动存储与地面军事系统上创建的存储桶连接起来。我上传了bucket中的文件夹“storage”,但应用程序中的所有图像都有404错误。 如何正确迁移GCS中的本地存储文件夹? 谢谢你的建议

  • 问题内容: 我已经看过所有类似的线程,阅读了文档,并尝试了许多组合来将空值存储在db中,并且每次都失败。 我正在使用MySQL。 我定义了一个字段。我从csv文件填充db,并且某些单元格没有值。Django文档说: 由于我正在与我一起工作,因此我希望将一个空字符串(csv中的一个空单元格)存储在db中。因此,我(认为)必须添加到该字段中。实际上,我已经尝试了更多: 每次我向数据库插入一个空字符串时

  • 我在一起使用和。 我是新来的,我想看一个变量的变化。 我想在我的

  • 我有两个组件Display.jsx和DisplayList.jsx。组件协同工作以显示本地存储中的值。问题在于DisplayList.JSX handleEdit()方法切片。 Github项目 我的想法: 我在这个论坛上问如何删除本地存储值,得到了这个答案,没有解释:堆栈溢出问题 它可以工作,但现在我需要做类似的切片来编辑旧的存储值并用新的存储值替换。但是我不知道怎么做。 总结:在方法handl