java HashMap中出现重复的key, 求解释

探讨了Java中HashMap在键对象属性变化后的行为表现,重点分析了hashcode与equals方法的作用及潜在的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


上代码:

        Person p1 = new Person("xiaoer",1);
        Person p2 = new Person("san",4);

        Map<Person,String> maps = new HashMap<Person,String>();
        maps.put(p1, "1111");
        maps.put(p2, "2222");
        System.out.println(maps);

        maps.put(p2, "333");
        System.out.println(maps);

        p1.setAge(5);
        System.out.println(maps);

        maps.put(p1, "333");
        System.out.println(maps);
        System.out.println(maps.get(p1));

输出结果:

{Person [name=san, age=4]=2222, Person [name=xiaoer, age=1]=1111}
{Person [name=san, age=4]=333, Person [name=xiaoer, age=1]=1111}
{Person [name=san, age=4]=333, Person [name=xiaoer, age=5]=1111}
{Person [name=san, age=4]=333, Person [name=xiaoer, age=5]=1111, Person [name=xiaoer, age=5]=333}
333


重点关注 红色的 标注。


其中Person类如下:

class Person{
    private String name;
    private int age;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}




why?   输出的maps 出现了相同的key。


初步 判断 和  HashMap的 hashcode机制有关, 只在第一次 将 元素  add 加入map时,检测元素key的 hash值。 之后我通过外部 手段 更改了对象的值,再将 该对象加入 map,其实 从hashcode来看 已经是一个新的 对象了,故 map认为他们的key 不同。HashMap为了提高校验速度,并不会 将待增的元素 与 map中已有的所有元素 一 一 比较,而只是快速的比较hashcode table 表?    虽然从物理内存上看 他们的确是 同一个对象。


java 这样设计的原理 何在?


这样其实存在不安全性。 譬如 我将一个 hashMap对象 传给了 方法A 去处理,结果A还在处理中的 时候,我把hashMap对象的里面的一个元素的值 给 简介更改了,而A 竟然还不知情。


 与 HashMap的线程不安全 是 几回事?







<think>好的,我现在需要回答用户的问题:“JavaHashMap允许键重复吗?”首先,我得回忆一下HashMap的基本特性。 我记得在Java中,HashMap是基于哈希表的Map接口实现。它的主要作用是存储键值对。接下来,关于键是否允许重复,应该是关键点。根据之前学的,HashMap的键是唯一的,不允许重复。也就是说,每个键只能映射到一个值。如果尝试插入重复的键,新值会覆盖旧值。 不过,我得确认一下这个知识点是否正确。可能需要查阅Java文档或者可靠的资料来验证。例如,当调用put方法时,如果键已存在,返回的是被替换的旧值,否则返回null。这说明确实不允许重复键,而是替换值。 另外,用户可能容易混淆键重复和值重复。需要明确指出,HashMap允许值重复,但键必须唯一。比如,可以有两个不同的键对应相同的值,但同一个键只能存在一次。 还要考虑线程安全的问题,虽然这可能不是用户当前的问题,但可以稍微提及,说明HashMap不是线程安全的,但在处理键唯一性时,多线程环境下可能需额外注意。 总结起来,回答的结构应该是先明确不允许键重复,然后解插入重复键时的行为,举例说明,并区分键和值的重复情况。如果有必要,可以提到相关的类比如Hashtable或ConcurrentHashMap,但用户的问题可能不需要深入这部分内容。 最后,确保用中文清晰表达,分步骤解,避免技术术语过于复杂,让用户容易理解。</think>在Java中,**HashMap不允许键重复**。以下是逐步说明: 1. **键的唯一性** HashMap要求所有键(key)必须是唯一的。如果尝试插入一个已存在的键(即使值不同),新值会**覆盖旧值**,而不会创建重复的键。 2. **插入重复键时的行为** 例如: ```java HashMap<String, Integer> map = new HashMap<>(); map.put("apple", 10); map.put("apple", 20); // 覆盖之前的键值对 System.out.println(map.get("apple")); // 输出:20 ``` 第二次调用`put("apple", 20)`时,键`"apple"`已存在,因此原值`10`被替换为`20`。 3. **值(value)允许重复** HashMap允许不同的键对应相同的值。例如: ```java map.put("apple", 20); map.put("banana", 20); // 允许:不同键,相同值 ``` 4. **底层原理** - HashMap通过哈希表实现,键的哈希码(`hashCode()`)和`equals()`方法决定键的唯一性。 - 插入新键时,会计算键的哈希值定位存储位置。若该位置已有相同键(通过`equals()`判断),则替换值。 5. **注意事项** - 若自定义对象作为键,必须正确重写`hashCode()`和`equals()`方法,否则可能导致键重复的误判。 - 线程不安全:多线程环境下操作HashMap可能导致键值覆盖或死循环(推荐使用`ConcurrentHashMap`)。 **总结**:HashMap的键不允许重复重复插入会覆盖旧值;值可以重复
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值