什么时候ReHash,HashMap的内部实现机制,Hash是怎样实现的 - schbook

2024-01-24 15:58

本文主要是介绍什么时候ReHash,HashMap的内部实现机制,Hash是怎样实现的 - schbook,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


原文:http://www.cnblogs.com/schbook/p/3585159.html?utm_source=tuicool&utm_medium=referral


1.HashMap的内部实现机制

HashMap是对数据结构中哈希表(Hash Table)的实现, Hash表又叫散列表。Hash表是根据关键码Key来访问其对应的值Value的数据结构,它通过一个映射函数把关键码映射到表中一个位置来访问该位置的值,从而加快查找的速度。这个映射函数叫做Hash函数,存放记录的数组叫做Hash表。

在Java中,HashMap的内部实现结合了链表和数组的优势,链接节点的数据结构是Entry<k,v>,每个Entry对象的内部又含有指向下一个Entry类型对象的引用,如以下代码所示:

static class Entry<K,V> implements Map.Entry<K,V> {  final K key;  V value;  Entry<K,V> next; //Entry类型内部有一个自己类型的引用,指向下一个Entry  final int hash;   ...
}  

在HashMap的构造函数中可以看到,Entry表被申明为了数组,如以下代码所示:

public HashMap() {  this.loadFactor = DEFAULT_LOAD_FACTOR;  threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);  table = new Entry[DEFAULT_INITIAL_CAPACITY];  init();  }  

在以上构造函数中, 默认的 DEFAULT_INITIAL_CAPACITY值为16,DEFAULT_LOAD_FACTOR的值为0.75。

当put一个元素到HashMap中去时,其内部实现如下:

public V put(K key, V value) {  if (key == null)  return putForNullKey(value);  int hash = hash(key.hashCode());  int i = indexFor(hash, table.length);  ...    
}  

可以看到put函数中用一个hash函数来得到哈希值,需要指出的是,HashTable在实现时直接用了hashCode作为哈希值,因此采用HashMap代替HashTable有一定的优化。

put函数中用到的两个函数hash和indexFor其实现分别如下:

static int hash(int h) {  // This function ensures that hashCodes that differ only by  // constant multiples at each bit position have a bounded  // number of collisions (approximately 8 at default load factor).  h ^= (h >>> 20) ^ (h >>> 12);  return h ^ (h >>> 7) ^ (h >>> 4);  }  
     /** * Returns index for hash code h. */  static int indexFor(int h, int length) {  return h & (length-1);  }  

至于hash函数为什么这样设计,这涉及到具体哈希函数的设计问题了,需要考虑的是哈希算法的时间复杂度,同时尽量使得数组上每个位置都有值,求得时间和空间的最优。

indexFor函数则用了一个很巧妙的与运算将index值限制在了length-1之内。

当然,hash函数存在冲突的情况,同一个key对应的hash值可能相同,这时候hash值相同的元素就会用链接进行存储,HashMap的get方法在获取value的时候会对链表进行遍历,把key值相匹配的value取出来。

2.Hash的实现

主要是哈希算法和冲突的解决。

3.什么时候ReHash

在介绍HashMap的内部实现机制时提到了两个参数,DEFAULT_INITIAL_CAPACITY和DEFAULT_LOAD_FACTOR,DEFAULT_INITIAL_CAPACITY是table数组的容量,DEFAULT_LOAD_FACTOR则是为了最大程度避免哈希冲突,提高HashMap效率而设置的一个影响因子,将其乘以DEFAULT_INITIAL_CAPACITY就得到了一个阈值threshold,当HashMap的容量达到threshold时就需要进行扩容,这个时候就要进行ReHash操作了,可以看到下面addEntry函数的实现,当size达到threshold时会调用resize函数进行扩容。

void addEntry(int hash, K key, V value, int bucketIndex) {  
ntry<K,V> e = table[bucketIndex];  table[bucketIndex] = new Entry<K,V>(hash, key, value, e);  if (size++ >= threshold)  resize(2 * table.length);  }  

在扩容的过程中需要进行ReHash操作,而这是非常耗时的,在实际中应该尽量避免。

 (原创文章,转载请注明作者schbook:seekerxu@163.com)


这篇关于什么时候ReHash,HashMap的内部实现机制,Hash是怎样实现的 - schbook的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/640194

相关文章

SpringBoot实现微信小程序支付功能

《SpringBoot实现微信小程序支付功能》小程序支付功能已成为众多应用的核心需求之一,本文主要介绍了SpringBoot实现微信小程序支付功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作... 目录一、引言二、准备工作(一)微信支付商户平台配置(二)Spring Boot项目搭建(三)配置文件

基于Python实现高效PPT转图片工具

《基于Python实现高效PPT转图片工具》在日常工作中,PPT是我们常用的演示工具,但有时候我们需要将PPT的内容提取为图片格式以便于展示或保存,所以本文将用Python实现PPT转PNG工具,希望... 目录1. 概述2. 功能使用2.1 安装依赖2.2 使用步骤2.3 代码实现2.4 GUI界面3.效

MySQL更新某个字段拼接固定字符串的实现

《MySQL更新某个字段拼接固定字符串的实现》在MySQL中,我们经常需要对数据库中的某个字段进行更新操作,本文就来介绍一下MySQL更新某个字段拼接固定字符串的实现,感兴趣的可以了解一下... 目录1. 查看字段当前值2. 更新字段拼接固定字符串3. 验证更新结果mysql更新某个字段拼接固定字符串 -

java实现延迟/超时/定时问题

《java实现延迟/超时/定时问题》:本文主要介绍java实现延迟/超时/定时问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java实现延迟/超时/定时java 每间隔5秒执行一次,一共执行5次然后结束scheduleAtFixedRate 和 schedu

Java Optional避免空指针异常的实现

《JavaOptional避免空指针异常的实现》空指针异常一直是困扰开发者的常见问题之一,本文主要介绍了JavaOptional避免空指针异常的实现,帮助开发者编写更健壮、可读性更高的代码,减少因... 目录一、Optional 概述二、Optional 的创建三、Optional 的常用方法四、Optio

在Android平台上实现消息推送功能

《在Android平台上实现消息推送功能》随着移动互联网应用的飞速发展,消息推送已成为移动应用中不可或缺的功能,在Android平台上,实现消息推送涉及到服务端的消息发送、客户端的消息接收、通知渠道(... 目录一、项目概述二、相关知识介绍2.1 消息推送的基本原理2.2 Firebase Cloud Me

Spring Boot项目中结合MyBatis实现MySQL的自动主从切换功能

《SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能》:本文主要介绍SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能,本文分步骤给大家介绍的... 目录原理解析1. mysql主从复制(Master-Slave Replication)2. 读写分离3.

Redis实现延迟任务的三种方法详解

《Redis实现延迟任务的三种方法详解》延迟任务(DelayedTask)是指在未来的某个时间点,执行相应的任务,本文为大家整理了三种常见的实现方法,感兴趣的小伙伴可以参考一下... 目录1.前言2.Redis如何实现延迟任务3.代码实现3.1. 过期键通知事件实现3.2. 使用ZSet实现延迟任务3.3

基于Python和MoviePy实现照片管理和视频合成工具

《基于Python和MoviePy实现照片管理和视频合成工具》在这篇博客中,我们将详细剖析一个基于Python的图形界面应用程序,该程序使用wxPython构建用户界面,并结合MoviePy、Pill... 目录引言项目概述代码结构分析1. 导入和依赖2. 主类:PhotoManager初始化方法:__in

springboot filter实现请求响应全链路拦截

《springbootfilter实现请求响应全链路拦截》这篇文章主要为大家详细介绍了SpringBoot如何结合Filter同时拦截请求和响应,从而实现​​日志采集自动化,感兴趣的小伙伴可以跟随小... 目录一、为什么你需要这个过滤器?​​​二、核心实现:一个Filter搞定双向数据流​​​​三、完整代码