我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java如何根据key值修改Hashmap中的value值

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java如何根据key值修改Hashmap中的value值

根据key值修改Hashmap的value值

如果原来map中没有key,会创建,如果原来有key,会使用value 覆盖掉原来的值

map.put(key,value);

这个实现对原值加一(前提是有这个key)

map.put(key,map.get(key)+1);

以下可以获取key对应的value,如果没有可以返回默认的value

map.getOrDefault(key,value);

HashMap的key更改后能否正确获取value?

在HashMap 中存放的一系列键值对,其中键为某个我们自定义的类型。放入 HashMap 后,我们在外部把某一个 key 的属性进行更改,然后我们再用这个 key 从 HashMap 里取出元素,这时候 HashMap 会返回什么?

我们办公室几个人答案都不一致,有的说返回null,有的说能正常返回value。但不论答案是什么都没有确凿的理由。我觉得这个问题挺有意思的,就写了代码测试。结果是返回null。需要说明的是我们自定义的类重写了 hashCode 方法。我想这个结果还是有点意外的,因为我们知道 HashMap 存放的是引用类型,我们在外面把 key 更新了,那也就是说 HashMap 里面的 key 也更新了,也就是这个 key 的 hashCode 返回值也会发生变化。这个时候 key 的 hashCode 和 HashMap 对于元素的 hashCode 肯定一样,equals也肯定返回true,因为本来就是同一个对象,那为什么不能返回正确的值呢?

测试案例

这里有 2 个案例,一个是 Person 类,还有一个是 Student 类,我们来验证下以上的观点(附带结论):

  • 修改了对象属性是否会改变它的 hashcode => 是的
  • 在 HashMap 里存取的时候是否会受到修改属性影响取值 => 取值为 null
package tech.luxsun.interview.luxinterviewstarter.collection;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.HashMap;
 

public class MapDemo0 {
 
    public static void main(String[] args) {
        HashMap<Object, Object> map = new HashMap<>();
 
        // Person Case
        Person p = new Person("Bob", 12);
        map.put(p, "person");
        System.out.println(p.hashCode());
        System.out.println(map.get(p));
 
        p.setAge(13);
        System.out.println(p.hashCode());
        System.out.println(map.get(p));
 
        // Student Case
        Student stu = new Student("Bob", 12);
        map.put(stu, "student");
        System.out.println(stu.hashCode());
        System.out.println(map.get(stu));
 
        stu.setAge(13);
        System.out.println(stu.hashCode());
        System.out.println(map.get(stu));
    }
}
 
@Data
@AllArgsConstructor
@NoArgsConstructor
class Person {
    private String name;
    private Integer age;
 
    public int hashCode() {
        return 123456;
    }
}
 
@Data
@AllArgsConstructor
@NoArgsConstructor
class Student {
    private String name;
    private Integer age;
}

输出结果

123456
person
123456
person
71154
student
71213
null

源码

hashCode 源码

public int hashCode() {
    int PRIME = true;
    int result = 1;
    Object $age = this.getAge();
    int result = result * 59 + ($age == null ? 43 : $age.hashCode());
    Object $name = this.getName();
    result = result * 59 + ($name == null ? 43 : $name.hashCode());
    return result;
}

map.get 源码


public V get(Object key) {
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}
 
 

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
 

final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {
        if (first.hash == hash && // always check first node
            ((k = first.key) == key || (key != null && key.equals(k))))
            return first;
        if ((e = first.next) != null) {
            if (first instanceof TreeNode)
                return ((TreeNode<K,V>)first).getTreeNode(hash, key);
            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    return e;
            } while ((e = e.next) != null);
        }
    }
    return null;
}

总之

可以看到先取得了一个table,这个table实际上是个数组。然后在table里面找对应 key 的value。找的标准就是hash等于传入参数的hash, 并且满足另外两个条件之一:k = e.key,也就是说他们是同一个对象,或者传入的 key 的equal目标的 key 。我们的问题出在那个hash(key.hashCode()),可以看到 HashMap 在存储元素时是把 key 的 hashCode 再做了一次hash。得到的hash将最终作为元素存储位置的依据。对应到我们的情况:第一次存储时,hash函数采用key.hashCode作为参数得到了一个值,然后根据这个值把元素存到了某个位置。

当我们再去取元素的时候,key.hashCode的值已经出现了变化,所以这里的hash函数结果也发生了变化,所以当它尝试去获得这个 key 的存储位置时就不能得到正确的值,导致最终找不到目标元素。要想能正确返回,很简单,把Person类的 hashCode 方法改一下,让它的 hashCode 不依赖我们要修改的属性,但实际开发中肯定不能这么干,我们总是希望当两个对象的属性不完全相同时能返回不同的 hashCode 值。

所以结论就是当把对象放到 HashMap 后,不要去修改 key 的属性,除非你重写了该实体类的 hashCode 方法不受属性限制。

最后

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java如何根据key值修改Hashmap中的value值

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java如何根据key值修改Hashmap中的value值

这篇文章主要介绍了Java如何根据key值修改Hashmap中的value值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-03-22

Java怎么根据key值修改Hashmap中的value值

这篇文章主要讲解了“Java怎么根据key值修改Hashmap中的value值”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java怎么根据key值修改Hashmap中的value值”吧!根
2023-07-05

如何在java中使用enum根据value值获取key键

这篇文章主要介绍了如何在java中使用enum根据value值获取key键,编程网小编觉得不错,现在分享给大家,也给大家做个参考,一起跟随编程网小编来看看吧!Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的
2023-06-06

java如何redis根据key查询值

Java中使用Redis根据Key查询值可通过Jedis或Redisson客户端库实现。Jedis用法:Jedisjedis=newJedis("localhost");Stringvalue=jedis.get("key");System.out.println(value);Redisson用法:RedissonClientredisson=Redisson.create();Stringvalue=redisson.getBucket("key").get();System.out.println(
java如何redis根据key查询值
2024-04-02

js如何修改对象数组的key值

本篇指南详细介绍了修改对象数组键值的方法,提供了使用Object.keys()和Object.defineProperty()以及for...in循环的示例。这两种方法允许调整对象键值,确保键值唯一性,并建议使用对象展开和Object.assign()来创建副本以便安全修改。
js如何修改对象数组的key值
2024-04-02

java中如何获取map的key值

在Java中,可以使用`Map`的`keySet()`方法获取`Map`的所有key值。`keySet()`方法返回一个`Set`集合,该集合包含`Map`中的所有key值。下面是一个示例代码:```javaimport java.util
2023-08-31

java如何获取object中某key的值

在Java中,可以通过以下方式获取object中某个key的值:使用JSONObject类:首先将object转换为JSONObject对象,然后使用get方法获取指定key的值。import org.json.JSONObject;JS
2023-10-24

java如何修改xml属性节点的值

在Java中,可以使用DOM解析器来修改XML属性节点的值。下面是一个示例代码:```javaimport java.io.File;import javax.xml.parsers.DocumentBuilder;import javax
2023-09-11

php如何根据值去除数组中的元素

这篇文章主要介绍了php如何根据值去除数组中的元素的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇php如何根据值去除数组中的元素文章都会有所收获,下面我们一起来看看吧。PHP中的数组是一种非常有用的数据结构,它
2023-07-05

vue中如何修改props传进来的值

大家应该都知道vue是单向数据流,一般我们也不会在子组件里面修改父组件传进来的值,但总有需要修改的时候,这篇文章主要介绍了vue中修改props传进来的值,需要的朋友可以参考下
2022-12-08

如何使用Java计算修改文件的MD5值

这篇文章主要介绍了如何使用Java计算修改文件的MD5值,MD5是一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值,用于确保信息传输完整一致,需要的朋友可以参考下
2023-05-15

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录