Java 11 HashMap 的hash计算细节分析

基于FastLIO2与TEB算法的机器狗自主导航系统实战 本文详细介绍了如何为机器狗构建一套基于FastLIO2与TEB算法的自主导航系统。通过整合FastLIO2激光惯性里程计实现精准定位,并采用TEB局部规划器进行灵活路径规划与动态避障,解决了传统方案在复杂地形下反应慢、易碰撞的问题。文章提供了从环境搭建、算法部署、地图转换到系统调试的完整实战指南,帮助开发者实现机器狗的稳健自主行走。 阅读详情

众所周知,java 中hashmap 基本的数据结构是 数组和 链表or 红黑树组成,在put或者get 操作的时候,计算数据下标是一个频繁的动作,本文分析一下java hashMap 的巧妙的算法设计。

首先数组下标必定是一个数字,java中HashMap 的最大值为 2>>30(2的30次方) 1073741824
实际场景中 hashMap的长度小于 2的16次方 (65536)

HashMap 的hash计算

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

这里并没有直接返回 key的hash值,而是根据key 的原始hash值 XOR 原始hash值的前16位

为什么要做计算

首先这个hash值除了进行key 的对比之后,还被用来计算 数据下标

 if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);

若使用原始hash值 计算数组下标也不是不可以,有人做了对比

package com.fancv.myCollentions;

import java.util.HashMap;

public class My {
    static final void intToTwo(int num) {
        String twoInt = "";
        for (int i = num; i != 0; i = i / 2) {
            if (i % 2 == 0) {
                twoInt = "0" + twoInt;
            } else {
                twoInt = "1" + twoInt;
            }
        }
        System.out.println(twoInt);
    }

    static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return n + 1;
    }

    public static void main(String[] args) {
        int cap = 1000;
        int[] probability1 = new int[cap];

        int[] probability2 = new int[cap];
        for (int ic = 0; ic < cap; ic++) {
            System.out.println("---------------");
            int hashLong = ("fanglile" + ic).hashCode();
            System.out.print(hashLong);
            System.out.print("  ");
            System.out.print((probability1[ic] = hashLong & (tableSizeFor(cap) - 1)));
            System.out.print("  ");
            intToTwo(hashLong);
            hashLong ^= hashLong >>> 16;
            System.out.print(hashLong);
            System.out.print("  ");
            System.out.print((probability2[ic] = hashLong & (tableSizeFor(cap) - 1)));
            System.out.print("  ");
            intToTwo(hashLong);
        }
        HashMap<Integer, Integer> map1 = new HashMap<>();
        for (int ic = 0; ic < probability1.length; ic++) {
            map1.put(probability1[ic], map1.containsKey(probability1[ic]) ? map1.get(probability1[ic]) + 1 : 1);
        }
        for (java.util.Map.Entry<Integer, Integer> e : map1.entrySet()) {
            System.out.println(e.getKey() + " 出现次数是:" + e.getValue());
        }
        System.out.println(map1.size());
        System.out.println("----------分割----------");
        HashMap<Integer, Integer> map2 = new HashMap<>();
        for (int ic = 0; ic < probability2.length; ic++) {
            map2.put(probability2[ic], map2.containsKey(probability2[ic]) ? map2.get(probability2[ic]) + 1 : 1);
        }
        for (java.util.Map.Entry<Integer, Integer> e : map2.entrySet()) {
            System.out.println(e.getKey() + " 出现次数是:" + e.getValue());
        }
        System.out.println(map2.size());
    }
}

图像化显示:
image

发现 使用了hash()之后 数据在数据中分布 更加集中在中间区域
分布更加平滑,优美。

为什么要右移16位

这里的16是基于经验设置的,java源码中很多例子都是作者根据多年经验设置的魔法数,例如hashMap的初始数组容量16 负载因子 0.75

为了是平衡性能和花销

这里的16位 是基于绝大多数情况下hashmap的长度不会超过65535,在根据数组(长度-1)&hash
计算数组下标的时候,hash的前16位不参与计算的,这就导致 数组下标的分布有集中的趋势,为了使得hash的前16位参与计算,需要无符号右移16位

为什么使用异或

异或运算

0 ^ 0 = 0;

1 ^ 0 = 1;

0 ^ 1 = 1;

1 ^ 1 = 0;

按位异或的3个特点:

(1)0异或任何数 = 任何数;

(2)1异或任何数 = 任何数取反;

(3)任何数异或自己 = 把自己置0;

java 的位运算 有| ^ &

and 或 or 趋向于 0 或者1 不利于后续数组下标的分散

XOR 更加合适

为什么使用 (length-1)&hash

计算数组下标一般都是 hash%(length)

但是这个计算比较耗费资源,所以在hashmap 设计的时候,规定 数组长度 是2 的N次方,最大

2>>30

这样使用了 hash&(length-1)==hash%length

AUTOSAR MCAL开发及EB Tresos工具使用总结 在基于AutoSar CP架构开发MCAL时,会使用到EB tresos工具。本文主要对MCAL开发及EB tresos工具使用进行总结,仅作为自学使用,以方便后续查漏补缺。 阅读详情

相关推荐

MyEclipse 2017 CI 10安装与激活

本文介绍MyEclipse 2017 CI 7、CI 8、CI 9和CI 10的安装与激活。此方法理论上应该能激活MyEclipse 2017 CI所有系列,即激活方法是通用的,只是激活文件略有不同。本文提供MyEclipse 2017 CI 7、CI 8、CI 9和CI 10的激活文件。说明:博主所提供的压缩包格式均为RAR5,即WinRAR 5.0以上的版本才能正常解压,别的压缩软件博主不太清...

weixin_42539046的博客 9416

Java HashMap——Hash算法

作为Java的一个重要的数据结构HashMap,其中很多地方值得我们思考,HashMap快速根据key找到Value的秘密到底在哪里? 下面我摘取了其中的核心算法 //重新计算哈希值 static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);//key如果是null 新hashcode是0 否则 计算新的hashcode }

weixin_43948683的博客 1697

《AI编程实战:深度学习模型改进与系统部署》,改进专栏目录和介绍

专深度学习相关项目都写在本专栏,《一次订阅解锁全部,都有源码,永久观看》,包括车牌识别、股票预测、人脸识别、风格迁移、图像修复、图像超分辨重建、图像分割等任务,Web/PyQt系统实现。引入Transformer、Swin Transformer、DenseNet、ViT、ConvNeXt等算法实战,提供卷积改进,魔改对比实验,模型剪枝,模型蒸馏,模型量化,全网独家整合改进专栏,为不同领域的同学发表论文提供了大力支持。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 3264

Java中两个long类型进行相加运算,值溢出的解决方法

博主在项目中遇到了这个需求,开始用的int类型进行运算,字段是存的字节,然后后台进行相应的逻辑运算返回给前台,前台来转化成GB。大家都知道1GB=1024MB,1MB=1024KB,1KB=1024Byte,所以1GB=1024*1024*1024=1073741824Byte。 所以问题来了,1GB的数据我后台就要存1073741824Byte,然后两个int类型进行相加直接溢出。 我们先来回...

riemann_的博客 2万+

Ascend开发包Acllite安装

设置环境变量,配置程序编译依赖的头文件,库文件路径。“$HOME/Ascend”请替换“Ascend-cann-toolkit”包的实际安装路径。将YOLOV7原始模型转换为适配昇腾310处理器的离线模型(*.om文件),放在model路径下。运行完成后,会在样例工程的out目录下生成推理后的图片,显示对比结果如下所示。可以使用以下两种方式下载,请选择其中一种进行源码准备。请从以下链接获取该样例的输入图片,放在data目录下。执行以下命令,执行编译脚本,开始样例编译。执行运行脚本,开始样例运行。

如果想成为中心,那么就到中心去吧。 317

YOLOv8改进 | Conv篇 | 利用YOLOv9的GELAN模块替换C2f结构(附轻量化版本 + 高效涨点版本 + 结构图)

本文给大家带来的改进机制是利用2024/02/21号最新发布的YOLOv9其中提出的GELAN模块来改进YOLOv8中的C2f,GELAN融合了CSPNet和ELAN机制同时其中利用到了RepConv在获取更多有效特征的同时在推理时专用单分支结构从而不影响推理速度,同时本文的内容提供了两种版本一种是参数量更低涨点效果略微弱一些的版本(参数量V8n下降80w,计算量为6.1GFLOPs),另一种是参数量稍多一些但是效果要不参数量低的效果要好一些(均为我个人整理),提供两种版本是为了适配不同需求的读者,具体选择

Snu77的博客 7564

java--HashMap源码之hash值计算(图解)

一、学习背景 最近在了解HashMap 存储元素的底层原理时,看到其中的hash 算法,运用到了位运算中的按位异或(^)、无符号右移(>>>),重新复习了下位运算的知识体系,文章以整数10和-10为例,进行讲解。 HashMap存储元素底层源码 二、图解位运算 十转二进制 ...

JustinQin 2395

Android CCodec (十一) Codec2Buffer BufferPool分析

1、序言 2、C2BlockPool分析 3、SimpleC2Component关于BlockingBlockPool的实现 4、总结

给大佬递杯卡布奇诺的博客 4020

java11 HashMap原理

二、方法 2.1 构造函数 /** * Constructs an empty <tt>HashMap</tt> with the specified initial * capacity and load factor. * * @param initialCapacity the initial capacity * @param loadFactor the load factor * @throws I

kking_edc的博客 488

高通开发系列 - Linux/Ubuntu移植到QCS8xxx平台

QCS8250和QRB5165平台属于体系架构相同的芯片,前置是带cellular而后者不带,即前置有移动网络而后者没有。 BSP部分的软件内容有差异需要修改外,同一套代码编译出来的执行程序是可以运行的,不会存在体系架构、指令集不匹配的问题。 QCS8250平台没有Linux/Ubuntu的软件SDK,只有Android的SDK,但是它对应j兼容的QRB5165平台有LE(Linux)和Ubun(Ubuntu)SDK。所以我们需要做的就是用QRB5165 Linux/Ubuntu移植到QCS8250平台上来

fulinux的博客 3185

RK3588 部署 YOLO26 目标检测:PT → ONNX → RKNN 全流程

YOLO26n 在 RK3588 上 INT8 量化后 NPU 推理约 15ms,系统 FPS 约 55,可以覆盖边缘端实时检测需求。模型从 PT 到 RKNN 的转换要用opset=11避免算子兼容问题。先用 YOLO26n + 640 输入跑通全链路,确认推理结果正确后再做性能调优。

m0_64661770的博客 303

Java 8系列之重新认识HashMap11

HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型。随着JDK(Java Developmet Kit)版本的更新,JDK1.8对HashMap底层的实现进行了优化,例如引入红黑树的数据结构和扩容的优化等。本文结合JDK1.7和JDK1.8的区别,深入探讨HashMap的结构实现和功能原理。

2401_89509470的博客 986

MuJoCo XLA (MJX) 强化学习人形机器人四足机器人入门教程(三)

MJX 是用 JAX 编写的 MuJoCo 实现,可以在 GPU/TPU 上进行大批量训练。在本笔记本中,我们将演示如何使用 MJX 训练 RL 策略。在开始大量 RL 工作负载之前,我们先从一个简单的示例开始!xml = """"""接下来,我们使用 MJX 将 MuJoCo 模型和数据放到 GPU 设备上。下面,我们将打印来自 MuJoCo 和 MJX 的 qpos。

2506_90492529的博客 2471

为什么 HashMap 要用 h^(h >>>16) 计算hash值?槽位数必须是 2^n?

大家好,我是一航! 昨天中午,一位粉丝朋友在微信私信我,问:为啥HashMap的hash值计算格式是这样:(h = key.hashCode()) ^ (h >>> 16)?h ^ (h >>> 16)是什么意思? 以下是Java8中HashMap计算key对应hash的源码: static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode().

一行Java的博客 5645

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

深入解析:ConcurrentHashMap 与 HashMap 中哈希值与索引计算的差异

在 Java 集合框架中,HashMap 和 ConcurrentHashMap 是两种非常重要的哈希表实现。尽管它们的核心功能类似,都是通过键的哈希值将键映射到对应的桶(bucket),但它们的设计目标和实现细节却大相径庭。尤其是在 哈希值的处理 以及 桶索引的计算 上,二者采取了不同的策略。 本文将详细解析 为什么 ConcurrentHashMap 需要显式地将负数哈希值转化为正数,而 HashMap 可以在计算索引时自动解决负数问题。

DC1020的博客 1031

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Java 哈希表(Hash Table)

Java 哈希表(Hash Table)全维度知识点总结

qq_59093178的博客 869

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Java集合-HashMap

Java集合-HashMap前言哈希算法哈希表什么是哈希表哈希函数详细描述处理冲突查找及分析java中的MapHashMap上帝视角:HashMap使用HashMap的put方法:MashMap的hash方法和hash桶数组索引位置:HashMap的resize()方法HashMap的长度保持2的次幂好处: 前言 了解HashMap前,我们先了解几个概念 哈希算法,是一类算法。 哈希表(Hash...

oheg2010的博客 576

Java HashMap 分析之二:Hash code

散列计算就是计算元素应该放在数组的哪个元素里。准确的说是放到哪个链表里面。按照Java的规则,如果你要想将一个对象放入HashMap中,你的对象的类必须提供hashcode方法,返回一个整数值。比如String类就有如下方法:public int hashCode() { int h = hash; int len = count; if (h ==

Dean Chen的专栏 9518

HashMap原理与细节

Java为数据结构的映射定义了一个接口,其中有四个常用实现类:HashMap、HashTable、LinkedHashMap和TreeMap。:根据键的hashCode值存储数据,允许一条记录的键为null,访问速度快,遍历顺序不稳定。HashMap线程不安全,并发环境可以使用Collections的syncronizedMap方法将它包装为线程安全的Map但是更推荐使用ConcurrentHashMap。JDK8以前HashMap使用数组+链表的数据结构,而JDK8。

yeheying的博客 1568

Java – HashMap详细说明

HashMap基于哈希算法工作,根据Java文档HashMap具有以下四个构造函数, 建设者 描述 HashMap ​() 构造一个空的 具有默认初始容量(16)和默认加载因子(0.75)的HashMap 。 HashMap ​(int initialCapacity) 构造一个空的 具有指定初始容量和默认加载因子(0.75)的HashMap 。 ...

最佳 Java 编程 1291

数据结构与算法-【算法专项】Hash算法-2(HashMap+设计Hash+Hash应用+Hashmap常用方法)

int value;// 必须重写hashCode方法@Override// 必须重写equals方法@Override注意:以上代码示例假设Integer和String是键和值的类型,实际使用时可以替换为任何实现了equals()和hashCode()方法的对象。

yinying293的博客 1241

java HashMap相关面试题

3.相关面试题 1.哈希表底层采用何种算法计算hash值?还有哪些算法可以计算出hash值? 底层采用的key值的hashCode()方法的值结合数组长度进行无符号右移16位(>>>)、按位异或(^)、按位与(&)计算出索引效率快 还可以采用:平方的取中法,取余数,伪随机数法,这些方法效率较慢 2.当两个对象的hashCode相等会怎么样? 会产生哈希碰撞,若key值内容相同则替换旧的value值,如果不相等,在java8之后在链表中使用链头法存储数据,如果链表的节点阈值超过八个,

菜鸟心声:学的不仅是技术,更是梦想! 400

java内存地址和哈希值_数据哈希值的计算和在table中的存储位置

我们知道,Objects中定义了hashcode()函数,用于计算对象的哈希值。并且在很多类中都对hashcode()函数进行了覆盖。但是在HashMap中并没有直接使用各个类的hash值,而是使用hash()函数将它再次进行了计算。一、列举一些基本类型对应的普通类型的hashcode()Objectspublic static int hashCode(Object o) {return o !...

weixin_29547309的博客 1051

Java HashMap详解

HashMap 版本:2018/8/2-1(2:14) HashMap HashMap原理分析 构造函数 数据结构 哈希算法 Entry HashSet LinkedHashMap 参考资料 1、HashMap是什么? Map族中最常用的集合 是Java Collection Framework的重要成员 Map是键值对映射的抽象接口,该映射只...

feather(猎羽) 456

史上最全HashMap面试题汇总

1.HashMap的数据结构? 哈希表结构(链表散列:数组+链表)实现,结合数组和链表的优点。当链表长度超过8时,链表转换为红黑树。 2.HashMap的工作原理? HashMap底层是hash数组和单向链表实现,数组中的每个元素都是链表,由Node内部类(实现Map.Entry<K,V>接口)实现,HashMap通过put&get方法存储和获取。 存储对象时,将K/V键值传给put()方法: ①、调用hash(K)方法计算K的hash值,然后结合数组长度,计算得数组下标;

一蓑烟雨任平生 2万+

彻底搞懂HashMap(上)

一、彻底搞懂HashMap(上) 文章概述: 相信很多朋友对于HashMap,开发中我们几乎每天都要使用它,但是每当问到map的一些原理时,很多朋友就不知道如何去回答,甚至一问三不知,从而离我们心仪的offer越来越远,那么今天借着咱们IT 巡游屋这个平台,和大家分享一下关于map的原理,让大家读完这篇文章后,再也不会因为map而倒在面试的路上 二、什么是哈希 • 什么是哈希 翻译成 “散列” ,就是把任意长度的输入,通过散列算法,变成固定长度的输出,该输出就是散列值,这个映射函数叫做散列函数,存

黑马程序员官方博客 313
上一篇: Mysql8.0 数据按照时间排序不稳定引发的思考
下一篇: 4.算法-所有数组的子集
hamish-wu
博客等级 码龄15年 2814粉丝 162原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值