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

JavaHashMap调整大小

如何解决《JavaHashMap调整大小》经验,为你挑选了2个好方法。

我们假设我们有一些代码

class WrongHashCode{
    public int code=0;

    @Override
    public int hashCode(){
        return code;
    }
}
public class Rehashing {
    public static void main(String[] args) {

        //Initial capacity is 2 and load factor 75%
        HashMap hashMap=new HashMap<>(2,0.75f);

        WrongHashCode wrOngHashCode=new WrongHashCode();
        //put object to be lost
        hashMap.put(wrongHashCode,"Test1");

        //Change hashcode of same Key object
        wrongHashCode.code++;

        //Resizing hashMap involved 'cause load factor barrier
        hashMap.put(wrongHashCode,"Test2");

        //Always 2
        System.out.println("Keys count " + hashMap.keySet().size());
    }
}

所以,我的问题是为什么在调整hashMap的大小之后(据我所知,直到重新调整键),我们仍然在keySet中有2个键而不是1个(因为现有的KV对的键对象是相同的)?



1> Gray..:

所以,我的问题是为什么在调整hashMap之后(到目前为止,据我所知,涉及重新调整键)

它实际上并没有,至少没有在-包括老调重弹键HashMap,除了在某些情况下(见下文)代码.它涉及在地图桶中重新定位它们.里面HashMap是一个Entry具有以下字段的类:

final K key;
V value;
Entry next;
int hash;

hash字段是存储的密钥,用于在进行put(...)调用时计算的密钥.这意味着如果更改对象中的哈希码,它将不会影响HashMap中的条目,除非您将其重新放入地图中.当然,如果您更改密钥的哈希码,您甚至无法在其中找到它,HashMap因为它具有与存储的哈希条目不同的哈希码.

我们仍然在keySet中有2个键而不是1个(因为现有的KV对的密钥对象是相同的)?

因此,即使您已更改单个对象的哈希值,它也会在地图中包含2个条目,其中包含不同的哈希字段.


总而言之,当调整HashMap的大小时,HashMap其中的代码可能会重新调整密钥 - 请参阅HashMap.transfer(...)jdk 7中的软件包保护方法(至少).这就是hash上面的字段不是的原因final.它仅在initHashSeedAsNeeded(...)返回true 时才使用"替代散列".以下设置启用alt-hashing的条目数阈值:

-Djdk.map.althashing.threshold=1

有了这个设置在VM上,我实际上能够hashcode()在调整大小时再次调用,但是我无法将第二个put(...)视为覆盖.问题的部分原因是,该HashMap.hash(...)方法是做与内部的XOR hashseed时调整大小会发生这变化,但之后put(...)记录进入进入新的哈希码.


这当然取决于`HashMap`的实现.我没有看过(例如)`LinkedHashMap`或`Map`的其他实现.没有什么能说`Map`实现不能多次调用`obj.hashcode()`,尽管如@jthlborn所说,这样做可能会很昂贵.

2> jtahlborn..:

HashMap实际上为每个键缓存 hashCode(因为键的hashCode计算起来可能很昂贵).因此,虽然您更改了现有键的hashCode,但它在HashMap中链接到的Entry仍然具有旧代码(因此在调整大小后将其置于"错误"桶中).

你可以在HashMap.resize()的jvm代码中看到这个(或者在java 6代码HashMap.transfer()中更容易看到).


推荐阅读
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
  • 解决.net项目中未注册“microsoft.ACE.oledb.12.0”提供程序的方法
    在开发.net项目中,通过microsoft.ACE.oledb读取excel文件信息时,报错“未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序”。本文提供了解决这个问题的方法,包括错误描述和代码示例。通过注册提供程序和修改连接字符串,可以成功读取excel文件信息。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
author-avatar
豹女无爱
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有