热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaHashMap内部数据结构在重新哈希处理期间如何变化?

如何解决《JavaHashMap内部数据结构在重新哈希处理期间如何变化?》经验,为你挑选了1个好方法。

我正在尝试编写演示代码,以显示当地图大小超过负载因子阈值时,Hashmap中正在发生重新哈希。我如何证明内部进行了哈希处理。我也想证明即使在重新哈希期间将旧条目移到新存储桶中,我也可以使用旧键来获取旧元素(让我知道我的假设是正确的)。下面的示例代码。

import java.util.*;

    class RehashDemo{

        public static void main(String[] args){
            Map numbers = new HashMap<>(10);
            for(int i = 0; i<10;i++){
                numbers.put(i,i+"");
            }
            System.out.println(numbers);

            for(int j = 15; j<=20;j++){
                numbers.put(j,j+"");
            }
            System.out.println(numbers);

        }


    }

Stuart Marks.. 6

编写演示哈希的程序并不难,但是您必须了解很多有关HashMap的内部组织,对象的哈希码如何生成,哈希码如何与HashMap的内部结构相关以及如何影响迭代顺序的知识。

简而言之,HashMap由一系列存储桶(“表”)组成。每个存储桶都是键值对的链接列表。将一对其键哈希值添加到已被占用的存储桶中,将其添加到该存储桶的链接列表的末尾。铲斗通过调用键的确定hashCode()方法,与它的高次异或它16位右无符号移了16(参照源),然后取表大小的模量。由于表的大小始终是2的幂,因此本质上是与(tablesize-1)的掩码进行“与”运算。Integer对象的哈希码只是其整数值。(来源)。最后,HashMap的迭代顺序依次遍历每个存储桶,还依次遍历每个存储桶内的对的链接列表。

毕竟,您可以看到小的整数值将最终出现在相应的存储桶中。例如,Integer.valueOf(0).hashCode()为0。在进行“异和”运算后,它将保持为0,并且任何表大小的模将保持为0。因此,整数0最终存储在存储区0中,整数1最终存储在存储区1中,依此类推。但是不要忘记,存储桶是表大小的模数。因此,如果表大小为8,则整数8将最终出现在存储区0中。

有了这些信息,我们可以用整数键填充HashMap,这些键将最终存储在可预测的存储桶中。让我们创建一个表大小为8且默认加载因子为0.75的HashMap,这意味着我们可以在重新哈希发生之前添加六个映射。

Map map = new HashMap<>(8);
map.put(0, 0);
map.put(8, 8);
map.put(1, 1);
map.put(9, 9);
map.put(2, 2);
map.put(10, 10);

{0=0, 8=8, 1=1, 9=9, 2=2, 10=10}

toString()如上所述,打印出地图(实质上是使用其方法)依次迭代地图。我们可以看到0和8出现在第一个存储桶中,1和9出现在第二个存储桶中,而2和10出现在第三个存储桶中。现在让我们添加另一个条目:

map.put(3, 3);

{0=0, 1=1, 2=2, 3=3, 8=8, 9=9, 10=10}

迭代顺序已更改!添加新映射超出了重新哈希的阈值,因此表大小增加了一倍,达到16。重新哈希已完成,这次模数为16而不是8。而0和8之前都在存储区0中,现在它们位于独立的存储桶,因为有可用存储桶的两倍。与1/9和2/10相同。当表大小为16时,旧表大小为8的每个存储桶中的第二个条目现在散列到其自己的存储桶中。您可以看到这一点,因为迭代顺序地通过存储桶进行,并且每个存储桶中现在都有一个条目。

当然,我仔细选择了整数值,以使表大小为8时不会发生冲突,而表大小为16时不会发生冲突。这使我们可以非常清楚地看到重新哈希。对于更典型的对象,很难预测哈希码(因此也包括存储桶),因此,很难看到冲突以及发生哈希时发生的变化。



1> Stuart Marks..:

编写演示哈希的程序并不难,但是您必须了解很多有关HashMap的内部组织,对象的哈希码如何生成,哈希码如何与HashMap的内部结构相关以及如何影响迭代顺序的知识。

简而言之,HashMap由一系列存储桶(“表”)组成。每个存储桶都是键值对的链接列表。将一对其键哈希值添加到已被占用的存储桶中,将其添加到该存储桶的链接列表的末尾。铲斗通过调用键的确定hashCode()方法,与它的高次异或它16位右无符号移了16(参照源),然后取表大小的模量。由于表的大小始终是2的幂,因此本质上是与(tablesize-1)的掩码进行“与”运算。Integer对象的哈希码只是其整数值。(来源)。最后,HashMap的迭代顺序依次遍历每个存储桶,还依次遍历每个存储桶内的对的链接列表。

毕竟,您可以看到小的整数值将最终出现在相应的存储桶中。例如,Integer.valueOf(0).hashCode()为0。在进行“异和”运算后,它将保持为0,并且任何表大小的模将保持为0。因此,整数0最终存储在存储区0中,整数1最终存储在存储区1中,依此类推。但是不要忘记,存储桶是表大小的模数。因此,如果表大小为8,则整数8将最终出现在存储区0中。

有了这些信息,我们可以用整数键填充HashMap,这些键将最终存储在可预测的存储桶中。让我们创建一个表大小为8且默认加载因子为0.75的HashMap,这意味着我们可以在重新哈希发生之前添加六个映射。

Map map = new HashMap<>(8);
map.put(0, 0);
map.put(8, 8);
map.put(1, 1);
map.put(9, 9);
map.put(2, 2);
map.put(10, 10);

{0=0, 8=8, 1=1, 9=9, 2=2, 10=10}

toString()如上所述,打印出地图(实质上是使用其方法)依次迭代地图。我们可以看到0和8出现在第一个存储桶中,1和9出现在第二个存储桶中,而2和10出现在第三个存储桶中。现在让我们添加另一个条目:

map.put(3, 3);

{0=0, 1=1, 2=2, 3=3, 8=8, 9=9, 10=10}

迭代顺序已更改!添加新映射超出了重新哈希的阈值,因此表大小增加了一倍,达到16。重新哈希已完成,这次模数为16而不是8。而0和8之前都在存储区0中,现在它们位于独立的存储桶,因为有可用存储桶的两倍。与1/9和2/10相同。当表大小为16时,旧表大小为8的每个存储桶中的第二个条目现在散列到其自己的存储桶中。您可以看到这一点,因为迭代顺序地通过存储桶进行,并且每个存储桶中现在都有一个条目。

当然,我仔细选择了整数值,以使表大小为8时不会发生冲突,而表大小为16时不会发生冲突。这使我们可以非常清楚地看到重新哈希。对于更典型的对象,很难预测哈希码(因此也包括存储桶),因此,很难看到冲突以及发生哈希时发生的变化。


推荐阅读
  • 类Hashtable<K,V>所有已实现的接口:Serializable,Cloneable,Map<K,V>此类实现一个哈希表,该哈希表将键映 ... [详细]
  • 如何在 Java LinkedHashMap 中高效地提取首个或末尾的键值对? ... [详细]
  • 我有3个来自RESEARCHS的映射值,指定要使用参考数据集填充的行中的范围。该研究 ... [详细]
  • 缓存这个东西就是为了提高运行速度的,由于缓存是在寸土寸金的内存里面,不是在硬盘里面,所以容量是很有限的。LRU这个算法就是把最近一次使用时间离现在时间最远的数据删除掉。先说说List:每 ... [详细]
  • 本篇文章给大家分享的是有关Java中怎么对HashMap按键值排序,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话 ... [详细]
  • 将学生对象和学生的归属地通过键与值存储到map集合中。importjava.util.HashMap;importjava.util.Iterator;importjava.uti ... [详细]
  • 01Map集合概述A:Map集合概述:我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同a:Collection中的集合 ... [详细]
  • 属性类 `Properties` 是 `Hashtable` 类的子类,用于存储键值对形式的数据。该类在 Java 中广泛应用于配置文件的读取与写入,支持字符串类型的键和值。通过 `Properties` 类,开发者可以方便地进行配置信息的管理,确保应用程序的灵活性和可维护性。此外,`Properties` 类还提供了加载和保存属性文件的方法,使其在实际开发中具有较高的实用价值。 ... [详细]
  • 本文详细介绍了 Java 中遍历 Map 对象的几种常见方法及其应用场景。首先,通过 `entrySet` 方法结合增强型 for 循环进行遍历是最常用的方式,适用于需要同时访问键和值的场景。此外,还探讨了使用 `keySet` 和 `values` 方法分别遍历键和值的技巧,以及使用迭代器(Iterator)进行更灵活的遍历操作。每种方法都附有示例代码和具体的应用实例,帮助开发者更好地理解和选择合适的遍历策略。 ... [详细]
  • 本文介绍了如何利用ObjectMapper实现JSON与JavaBean之间的高效转换。ObjectMapper是Jackson库的核心组件,能够便捷地将Java对象序列化为JSON格式,并支持从JSON、XML以及文件等多种数据源反序列化为Java对象。此外,还探讨了在实际应用中如何优化转换性能,以提升系统整体效率。 ... [详细]
  • HashTable与ConcurrentHashMap均可实现HashMap的功能,对外提供了键值对存储的数据结构。但是在内部结构及实现上有何区别,性能上的差异到底在哪里又是如何导致的 ... [详细]
  • 使用Maven JAR插件将单个或多个文件及其依赖项合并为一个可引用的JAR包
    本文介绍了如何利用Maven中的maven-assembly-plugin插件将单个或多个Java文件及其依赖项打包成一个可引用的JAR文件。首先,需要创建一个新的Maven项目,并将待打包的Java文件复制到该项目中。通过配置maven-assembly-plugin,可以实现将所有文件及其依赖项合并为一个独立的JAR包,方便在其他项目中引用和使用。此外,该方法还支持自定义装配描述符,以满足不同场景下的需求。 ... [详细]
  • 转载自:http:www.blogjava.netCarpenterLeearchive20160427430268.html总体介绍之所以把HashSet和HashMa ... [详细]
  • ***功能:排序*privatestaticvoidoutputRegionStatistics(HashMap<String,Integer>regionMap){ ... [详细]
  • 写这篇文章起源于一道面试题,如何将自定义的类对象作为key存储到HashMap中,即考虑怎么判断key的唯一性。首先,我们看以下HashMap中put(…)方法的源码:public ... [详细]
author-avatar
chuntianhuaji
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有