热门标签 | 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时不会发生冲突。这使我们可以非常清楚地看到重新哈希。对于更典型的对象,很难预测哈希码(因此也包括存储桶),因此,很难看到冲突以及发生哈希时发生的变化。


推荐阅读
  • Whenoverridingtheequals()functionofjava.lang.Object,thejavadocssuggestthat,当重写java.lang. ... [详细]
  • 查找给定字符串的所有不同回文子字符串原文:https://www ... [详细]
  • java散列与散列码探讨,简单HashMap实现散列映射表执行各种操作示列packageorg.rui.collection2.maps;***散列与散列码*将土拔鼠对象与预报对象联系 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • 使用freemaker生成Java代码的步骤及示例代码
    本文介绍了使用freemaker这个jar包生成Java代码的步骤,通过提前编辑好的模板,可以避免写重复代码。首先需要在springboot的pom.xml文件中加入freemaker的依赖包。然后编写模板,定义要生成的Java类的属性和方法。最后编写生成代码的类,通过加载模板文件和数据模型,生成Java代码文件。本文提供了示例代码,并展示了文件目录结构。 ... [详细]
  • Annotation的大材小用
    为什么80%的码农都做不了架构师?最近在开发一些通用的excel数据导入的功能,由于涉及到导入的模块很多,所以开发了一个比较通用的e ... [详细]
  • 我有一个xml文件,里面的数据想放入自定义类里存入HashTable里面,不知道有没有哪为高手有这方面的例子,希望能解小弟一时之困!谢谢! ... [详细]
  • 一、HashMap1.HashMap概述:HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是 ... [详细]
  • 常用API-Hashtable类及其与HashMap、HashSet的区别转载请表明出处:http:blog.csdn.netu012637501(嵌入式_小J的天空)一、Hashtable&l ... [详细]
  • (2.1.8)Java之集合类:set、list、hashmap、hashtable等和迭代器iterator
    一、容器常见的集合类有这些种:实现Collection接口的:Set、List以及他们的实现类。实现Map接口的:HashMap及其实现类编程爱好者学习,下面我我们通过一个图来整体描述一下:这个图片没 ... [详细]
  • 用户购买商品时if(e.CommandName.ToLower()"buy"){判断用户购物车是否为空如果为空则分配 ... [详细]
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社区 版权所有