hashmap有关问题与计算

1.HashMap的存储方式是数组加链表,主干是一个Entry数组。Entry是HashMap的基本组成单元,每一个Entry包含一个key-value键值对;当不同的key经过hash计算得出的index值相同时,就需要在数组里添加一个链表来存储index相同的元素,HashMap的整体结构如下:

简单来说,HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。

2.需要注意的是,新来的Entry节点插入链表时,使用的是“头插法”。之所以把新来的节点放在头节点,是因为HashMap的发明者认为,后插入的Entry被查找的可能性更大,这就是HashMap的底层原理,

HashMap的默认初始长度是16,并且每次自动扩展或是手动初始化时,长度必须是2的幂

初始长度16是为了服务于从Key映射到index的Hash算法

从Key映射到HashMap数组的对应位置,会用到一个Hash函数,比如调用 hashMap.put("book", 0) ,插入一个Key为“book"的元素。这时候我们需要利用一个哈希函数来确定Entry的插入位置(index):

index = Hash(“book”)---->> index = HashCode(Key) & (Length - 1)//这里Key为book,Length是HashMap的长度

整个过程如下:

1)计算book的hashcode,结果为十进制的3029737,二进制的101110001110101110 1001。

2)假定HashMap长度是默认的16,计算Length-1的结果为十进制的15,二进制的1111。

3)把以上两个结果做与运算,101110001110101110 1001 & 1111 = 1001,十进制是9,所以 index=9。可以说,Hash算法最终得到的index结果,完全取决于Key的Hashcode值的最后几位。

假设HashMap的长度是10,重复刚才的运算步骤

 HashMapåºå±æ°æ®ç»æåç

单独看这个结果,表面上并没有问题。我们再来尝试一个新的HashCode 101110001110101110 1011 :

HashMapåºå±æ°æ®ç»æåç

再换一个HashCode 101110001110101110 1111 试试 :

HashMapåºå±æ°æ®ç»æåç

虽然HashCode的倒数第二第三位从0变成了1,但是运算的结果都是1001。也就是说,当HashMap长度为10的时候,有些index结果的出现几率会更大,而有些index结果永远不会出现(比如0111)!

这样,显然不符合Hash算法均匀分布的原则。

反观长度16或者其他2的幂,Length-1的值是所有二进制位全为1,这种情况下,index的结果等同于HashCode后几位的值。只要输入的HashCode本身分布均匀,Hash算法的结果就是均匀的。

(这点也涉及到了JAVA中hashCode()与equals()区别与作用:hashCode也可以用来比较对象是否相同,且效率高于equals,equals的效率很低下。但hashCode()并不是完全可靠,不同的对象也可能生成相同的hashcode,而equals是完全可靠的。

 所有对于需要大量并且快速的对比的话如果都用equal()去做显然效率太低,所以解决方式是,每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了),如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!)

(hashCode值的计算方式:具体可以参考不同版本的jdk api内的 hashCode函数)

3.HashMap非线程安全

1)Hashmap在插入元素过多的时候需要进行Resize,Resize的条件是

HashMap.Size >= Capacity * LoadFactor。

2)Hashmap的Resize包含扩容和ReHash两个步骤,ReHash在并发的情况下可能会形成链表环。

为ä»ä¹HashMapé线ç¨å®å¨

https://blog.csdn.net/wufaliang003/article/details/80219296

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/418358.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端学习(1991)vue之电商管理系统电商系统之实现商品的分页功能

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

java httpclient发送json 请求 ,go服务端接收

/***java客户端发送http请求*/package com.xx.httptest;/*** Created by yq on 16/6/27.*/import java.io.IOException; import java.net.URLEncoder; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.co…

linux 定时备份mysql数据库

首先要先搞清楚两个概念: ①、mysqldump,mysqldump是mysql的逻辑备份工具,它不是linux的命令,工作原理类似产生一些列sql语句,对数据库进行指定的逻辑备份。 最简洁的形式是:mysqldump -uuserName -ppassW…

前端学习(1992)vue之电商管理系统电商系统之实现搜索和清空

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

4123: 马走日,2797:最短前缀 Trie,2362:Square 能否拼接为正方形

4123: 马走日 深度优先搜索 回溯 ///马走日 int f[21][22],n,m,t; //f数组记录点有没有走过int x[10]{-2,-2,-1,1,2,2,1,-1},y[10]{-1,1,2,2,1,-1,-2,-2};//八个方向 int x1,y1,ans; void dfs(int a,int b) //搜索过程 {bool ptrue; //标记,判断马是否可以遍…

前端学习(1993)vue之电商管理系统电商系统之根据id删除数据

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

苹果开发者地址1

https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app转载于:https://www.cnblogs.com/zhangchengyuan/p/5623348.html

C++算法一些常用的stl函数

1.lower_bound( )和upper_bound( ) lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的 在从小到大的排序数组中, lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字&a…

LINUX 常用命令集合

su su命令是最基本的命令之一,常用于不同用户间切换。例如,如果登录为 user1,要切换为user2,只要用如下命令: $su user2 然后系统提示输入user2口令,输入正确的口令之后就可以切换到user2。完成之后就可…

前端学习(1994)vue之电商管理系统电商系统之通过编程导航跳转到商品导航界面

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

转载CSDN博客步骤

转载CSDN博客步骤: 1.CSDN博客页面右键,点击【检查】 点击检查后,页面右侧出现html代码,如下图 2.如果需要转载全文,则在html代码下侧点击选中article_content 即可,会在代码框中自动选中article_co…

android深度探索 HAL及驱动开发 第八章

第八章 读书笔记 本章主要讲蜂鸣器的驱动,蜂鸣器是S3cC6410开发板上带的一个硬件设备,本节将介绍蜂鸣器的实现原理,并实现一个完整的蜂鸣器驱动。本节讲介绍把linux驱动分成多个文件的方式。这些文件中的数据结构、函数的代码也可以被多个不同…

前端学习(1995)vue之电商管理系统电商系统之添加页面的基本结构

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

JDK1.7和JDK1.8中HashMap是线程不安全的,并发容器ConcurrentHashMap模型

一、HashMap是线程不安全的 前言 只要是对于集合有一定了解的一定都知道HashMap是线程不安全的,我们应该使用ConcurrentHashMap。但是为什么HashMap是线程不安全的呢,之前面试的时候也遇到到这样的问题,但是当时只停留在***知道是***的层面上…

前端学习(1996)vue之电商管理系统电商系统之美化步骤条

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

三种基本背包问题

一、0/1背包问题 问题描述:有n件物品和容量为m的背包 给出i件物品的重量以及价值 求解让装入背包的物品重量不超过背包容量 且价值最大 。 特点:这是最简单的背包问题,特点是每个物品只有一件供你选择放还是不放。 ① 二维解法 设f[i][j]表示前 i 件物品…

java中sesion

Session*Cookie基于客户端,不安全,并且大小和个数的限制。*Session域对象,范围一次会话范围,存个人相关的数据。*setAttribute(String name,Object value);*Object getAttribute(String name);*String getId() 获取session的唯一的…

前端学习(1997)vue之电商管理系统电商系统之渲染tab栏标签

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

LeetCode刷题过程中的一些小tips

0. 1. 发现没,与数组遍历、当前元素和前后元素大小比较 相关的都用单调栈 2. sql运行顺序查一下(运行顺序依次是from、where、group by、select order by。先根据s1.Id进行分组,然后计算(count)组内大于等于score的个数(去重),也…

Android之WebView网页滚动截图

WebView 网页滚动截屏,可对整个网页进行截屏而不是仅当前屏幕哦! 注意若Web页面存在position:fixed; 的话得在调用前设置为 position:absolute; 哦,否则会出现很多次的,请看下面的具体解说吧!! private st…