首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

再撸一次HashMap

只是在JDK1.8链表长度大于8时候,链表会转成红黑树! 为什么用数组+链表? 数组是用来确定桶位置,利用元素keyhash对数组长度取模得到....HashMap为了存取高效,要尽量较少碰撞,就是要尽量把数据分配均匀,每个链表长度大致相同,这个实现就在把数据存到哪个链表算法;这个算法实际就是取模,hash%length。...java.lang.Object@74a14482 null 如果让你实现一个自定义class作为HashMapkey该如何实现?...(4)通过构造器初始化所有成员,进行深拷贝(deep copy) 如果构造器传入对象直接赋值给成员变量,还是可以通过对传入对象修改进而导致改变内部变量。...为了保证内部不被修改,可以采用深度copy来创建一个新内存保存传入

54310

HashMap面试必问6个点,你知道几个?

只是在JDK1.8链表长度大于8时候,链表会转成红黑树! 2.为什么用数组+链表? 数组是用来确定桶位置,利用元素keyhash对数组长度取模得到....HashMap为了存取高效,要尽量较少碰撞,就是要尽量把数据分配均匀,每个链表长度大致相同,这个实现就在把数据存到哪个链表算法;这个算法实际就是取模,hash%length。...java.lang.Object@74a14482 null 4.如果让你实现一个自定义class作为HashMapkey该如何实现?...(4)通过构造器初始化所有成员,进行深拷贝(deep copy) 如果构造器传入对象直接赋值给成员变量,还是可以通过对传入对象修改进而导致改变内部变量。...为了保证内部不被修改,可以采用深度copy来创建一个新内存保存传入

1.5K11
您找到你想要的搜索结果了吗?
是的
没有找到

如何保证集合是线程安全? ConcurrentHashMap如何实现高效地线程安全?

幸好 Java 语言提供了并发包(java.util.concurrent),为高度并发需求提供了更加全面的工具支持 今天要问你问题是,如何保证容器是线程安全?...具体选择要看开发场景需求,总体来说,并发包内提供容器通用场景,远优于早期简单同步实现 考点分析 谈到线程安全和并发,可以说是 Java 面试必考考点,上面给出回答是一个相对宽泛总结,而且...如果要深入思考并回答这个问题及其扩展方面,至少需要: 理解基本线程安全工具。 理解传统集合框架并发编程 Map 存在问题,清楚简单同步方式不足。...2.ConcurrentHashMap 分析 我们再来看看 ConcurrentHashMap 是如何设计实现为什么它能大大提高并发效率。...,以最优化性能,毕竟 Unsafe 很多操作都是 JVM intrinsic 优化过 可以参考下面这个早期 ConcurrentHashMap 内部结构示意图,其核心是利用分段设计,在进行并发操作时候

55730

如何保证集合是线程安全? ConcurrentHashMap如何实现高效地线程安全?

今天要问你问题是,如何保证容器是线程安全?ConcurrentHashMap如何实现高效地线程安全?典型回答Java提供了不同层面的线程安全支持。...考点分析谈到线程安全和并发,可以说是Java面试必考考点,上面给出回答是一个相对宽泛总结,而且ConcurrentHashMap等并发容器实现也在不断演进,不能一概而论。...如果要深入思考并回答这个问题及其扩展方面,至少需要:理解基本线程安全工具。理解传统集合框架并发编程Map存在问题,清楚简单同步方式不足。...2.ConcurrentHashMap分析我们再来看看ConcurrentHashMap是如何设计实现为什么它能大大提高并发效率。...今天从线程安全问题开始,概念性总结了基本容器工具,分析了早期同步容器问题,进而分析了Java 7和Java 8ConcurrentHashMap是如何设计实现,希望ConcurrentHashMap

43420

「Java面试题精华集」1w字Java集合框架篇(2020最新版)附PDF版 !

为什么呢?觉得还是和底层数据结构有关!ArrayList 底层是数组,而 LinkedList 底层是链表。数组天然支持随机访问,时间复杂度为 O(1),所以称为快速随机访问。...但问题是一个 40 亿长度数组,内存是放不下。所以这个散列不能直接拿来用。用之前还要先做对数组长度取模运算,得到余数才能用来要存放位置也就是对应数组下标。...这个数组下标的计算方法是“ (n - 1) & hash”。(n 代表数组长度)。这也就解释了 HashMap 长度为什么是 2 幂次方。 这个算法应该如何设计呢?...另外,在单线程下,如果在遍历过程对集合对象内容进行了修改的话也会触发 fail-fast 机制。 “注:增强 for 循环也是借助迭代器进行遍历。...所以,在遍历过程对原集合所作修改不能被迭代器检测到,故不会抛 ConcurrentModificationException 异常。

1.2K20

【JAVA】ConcurrentHashMap 如何实现高效地线程安全?

2、ConcurrentHashMap 分析 我们再来看看 ConcurrentHashMap 是如何设计实现为什么它能大大提高并发效率。...首先,这里强调,ConcurrentHashMap 设计实现其实一直在演化,比如在 Java 8 中就发生了非常大变化(Java 7 其实也有不少更新),所以,这里将比较分析结构、实现机制等方面...现代 JDK ,synchronized 已经被不断优化,可以不再过分担心性能差异,另外,相比于 ReentrantLock,它可以减少内存消耗,这是个非常大优势。...这个东西非常小众,大多数情况下,建议还是使用 AtomicLong,足以满足绝大部分应用性能需求。   后记 以上就是 【JAVA】ConcurrentHashMap 如何实现高效地线程安全? ...所有内容了; 从线程安全问题开始,概念性总结了基本容器工具,分析了早期同步容器问题,进而分析了 Java 7 和 Java 8 ConcurrentHashMap 是如何设计实现,希望 ConcurrentHashMap

19430

HashMap你真的了解吗?

存储这个哈希是为了避免每次 HashMap 需要它时计算哈希。 这是 JAVA 7 Entry 实现一部分: HashMap 将数据存储到多个条目的单链表(也称为桶或箱)。...例如,假设您有一个仅将新数据放入 Map Writer 线程和一个从 Map 读取数据 Reader 线程,为什么不能工作?...“2” 修改了keyhash但是HashMap不知道(因为存储了旧hash) 您尝试使用修改密钥获取对象 该映射计算您新哈希(因此从“2”开始)以查找条目在哪个链表(桶) 案例 1...由于您修改密钥与旧哈希(存储在条目中)哈希不同,因此映射不会在链表中找到该条目。 这是Java一个具体示例。... Map 中放置了 2 个键值对,修改了第一个键,然后尝试获取这 2 个

2.2K30

呕心沥血,独到见解:JUC集合类,独到见解。

注意:普通集合类,太过于基础,这里仅仅是简单回顾,还需要大家有相应基础哈另外:配合并发编程专栏线程池学习并发队列效果更佳。...),每个segment之间互不影响,提高了并发效率默认有16个segment,也就是说,最多支持16个线程并发写能力,这个16默认,可以在初始化concurrnetHash时候修改这是1.7,...这么厉害,先看看代码例子,演示一下注意:arrayList不能迭代时候修改,报并发修改异常 ,属于fail-fast机制,这个基础八股就不多讲了哈,这里主要看copyOnwriteList可以并发修改这是...你管你修改管我迭代!...另外,copyOnwriteArrayList读写分离,读时候不会因为Synchronized阻塞读线程读操作这只是偶然发现,正确性有待考证。

35920

面试官再问你 HashMap 底层原理,就把这篇文章甩给他看

//为什么设置 0.75 这个呢,简单来说就是时间和空间权衡。...key,value传入进来 //这里onlyIfAbsent如果为true,表明不能修改已经存在,因此我们传入false //evict只有在方法 afterNodeInsertion(boolean...//为什么这样说呢,之前在 tableSizeFor 卖了个关子,需要注意是,它返回是赋给了 threshold 而不是 capacity。...JDK1.8做了改进,用是尾插法,不会产生死循环。 那么,链表是怎么形成环状呢? 关于这一点解释,发现网上文章抄来抄去,而且都来自左耳朵耗子,更惊奇是,连配图都是一模一样。...(别问我为什么知道,因为也看过耗子叔文章,哈哈。然而,菜鸡,那篇文章,并没有看懂。。。) 实在看不下去了,于是一怒之下,就有了这篇文章。

46922

javahashcode用法_javahashcode作用

,那么就在这个Hash key地方产生一个链表,将所有产生相同hashcode对象放到这个链表上去,串在一起。...一、为什么HashCode对于对象是如此重要: 一个对象HashCode就是一个简单Hash算法实现,虽然它和那些真正复杂Hash算法相比还不能叫真正算法,它如何实现它,不仅仅是程序员编程水平问题...从上面看可以看到,对于HashMap和Hashtable 存取性能有重大影响首先是应该使该数据结构元素尽量大可能具有不同HashCode,虽然这并不能保证不同HashCode产生不同 index...既然可以根据HashCode直接定位对象在Hashtable位置,那么为什么Hashtable要用key来做映射呢(为了一些思维有障碍的人能看到懂加了一句话:而不是直接放value呢)?...从上面看可以看到,对于HashMap和Hashtable存取性能有重大影响首先是应该使该数据结构元素尽量大可能具有不同HashCode,虽然这并不能保证不同HashCode产生不同index

90520

Java集合面试题

Java 平台不提供这个接口任何直接实现。 Set ,是一个不能包含重复元素集合。这个接口对数学集合抽象进行建模,被用来代表集合,就如一副牌。 List ,是一个有序集合,可以包含重复元素。...另外,LinkedHashMap 在上面结构基础上,增加了一条双向链表,使得上面的结构可以保持键值对插入顺序。同时通过对链表进行相应操作,实现了访问顺序相关逻辑。...因为不同 key ,可能有相同 hashcode ,所以 value 需要是链表结构。 他们共同点都是 hash 算法实现唯一性,他们都不能持有基本类型,只能持有对象。...因为 HashMap 使用链表存储对象,这个 Entry(包含有键值对 Map.Entry 对象)会存储在链表。 ? hashCode 和 equals 方法有何重要性?...为了能让 HashMap 存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀,每个链表/红黑树长度大致相同。这个实现就是把数据存到哪个链表/红黑树算法。 这个算法应该如何设计呢?

51420

Java基础问题整理「建议收藏」

(下图作为参考) HashSet和HashMap 另外:Synchronized实现原理 5.Hash1.7是基于数组和链表实现为什么不用双链表?HashMap1.8引入红黑树原因是?...补充知识点: HashMap如果想要让自己Object作为K应该怎么办?...5.Hash1.7是基于数组和链表实现为什么不用双链表?HashMap1.8引入红黑树原因是?为什么要用红黑树而不是平衡二叉树?...比如,线程A修改了自己共享变量副本,这时如果该共享变量没有被volatile修饰,那么本次修改不一定会马上将修改结果刷新到主存,如果此时B去主存读取共享变量,那么这个就是没有被A修改之前...如果该共享变量被volatile修饰了,那么本次修改结果会强制立刻刷新到主存,如果此时B去主存读取共享变量,那么这个就是被A修改之后值了。

30930

Java 集合(List、Set、Map 等)相关问答归纳再整理

可是问题又来了,对象数组又不能适应变化需求,因为数组长度是固定,而且他不能根据我们操作(增删改查)选择最好策略,这个时候,为了适应变化需求,Java就提供了集合类供我们使用。...另外,LinkedHashMap 在上面结构基础上,增加了一条双向链表,使得键值对插入顺序以及访问顺序等逻辑可以得以实现。...(除非使用方法瘦身) 2.2 ArrayLsit 扩容机制和并发修改异常(请跳转) 在 001-ArrayList源码分析(含扩容机制等重点问题分析) 文章做过详细分析,篇幅过长,可跳转阅读。...具体分析可参考在知乎回答:Java遍历HashSet为什么输出是有序?@BWH_Steven 答案 这个问题非常值得深入分析,对于 Set 和 Map 源码理解很有帮助!!!...我们在hashCoe方法返回到了一个等同于本身散列,但是考虑到int类型数据范围:-2147483648~2147483647 ,着很显然,这些散列不能直接使用,因为内存是没有办法放得下,一个

75130

HashMap源码分析(一)(超级详细)

当一个要存储到Map时候会根据Key来计算出他 hash,通过哈希来确认到数组位置,如果发生哈希碰撞就以链表形式存储 在Object源码分析解释过,但是这样如果链表过长来的话,HashMap...这个问题也没有想过,其实很多在看时候只会在乎红黑树实现而忽略到了为什么要使用这个问题,也是在写本文时候突发疑惑。...当链表长度很小时候,即使遍历,速度也非常快,但是当链表长度不断变长,肯定会对查询性能有一定影响,所以才需要转成树。至于为什么阈值是8,想,去源码找寻答案应该是最可靠途径。...显然,JDK维护者,后来不认为这个小小失误值得去修改,所以就这样存在下来了。...当Map里面的数量超过这个时,表桶才能进行树形化 ,否则桶内元素太多时会扩容,而不是树形化 为了避免进行扩容、树形化选择冲突,这个不能小于 4 * TREEIFY_THRESHOLD ?

45830

HashMap源码分析(一)(超级详细)

当一个要存储到Map时候会根据Key来计算出他 hash,通过哈希来确认到数组位置,如果发生哈希碰撞就以链表形式存储 在Object源码分析解释过,但是这样如果链表过长来的话,HashMap...这个问题也没有想过,其实很多在看时候只会在乎红黑树实现而忽略到了为什么要使用这个问题,也是在写本文时候突发疑惑。...当链表长度很小时候,即使遍历,速度也非常快,但是当链表长度不断变长,肯定会对查询性能有一定影响,所以才需要转成树。至于为什么阈值是8,想,去源码找寻答案应该是最可靠途径。...显然,JDK维护者,后来不认为这个小小失误值得去修改,所以就这样存在下来了。 ?...当Map里面的数量超过这个时,表桶才能进行树形化 ,否则桶内元素太多时会扩容,而不是树形化 为了避免进行扩容、树形化选择冲突,这个不能小于 4 * TREEIFY_THRESHOLD ?

35320

HashMap源码分析(一)(超级详细)

当一个要存储到Map时候会根据Key来计算出他 hash,通过哈希来确认到数组位置,如果发生哈希碰撞就以链表形式存储 在Object源码分析解释过,但是这样如果链表过长来的话,HashMap...这个问题也没有想过,其实很多在看时候只会在乎红黑树实现而忽略到了为什么要使用这个问题,也是在写本文时候突发疑惑。...当链表长度很小时候,即使遍历,速度也非常快,但是当链表长度不断变长,肯定会对查询性能有一定影响,所以才需要转成树。至于为什么阈值是8,想,去源码找寻答案应该是最可靠途径。...显然,JDK维护者,后来不认为这个小小失误值得去修改,所以就这样存在下来了。 ?...当Map里面的数量超过这个时,表桶才能进行树形化 ,否则桶内元素太多时会扩容,而不是树形化 为了避免进行扩容、树形化选择冲突,这个不能小于 4 * TREEIFY_THRESHOLD ?

51330

构建高性能队列,你不得不知道底层知识!

前言 本文收录于专辑:http://dwz.win/HjK,点击解锁更多数据结构与算法知识。 你好,是彤哥。 上一节,我们一起学习了如何将递归改写为非递归,其中,用到数据结构主要是栈。...栈和队列,可以说是除了数组和链表之外最基础数据结构了,在很多场景中都有用到,后面我们也会陆陆续续看到。 今天,想介绍一下,在Java如何构建一个高性能队列,以及我们需要掌握底层知识。...使用数组和链表实现简单队列,我们前面都介绍过了,这里就不再赘述了,有兴趣同学可以点击以下链接查看: 重温四大基础数据结构:数组、链表、队列和栈 今天我们主要来学习如何实现高性能队列。...本例其实还有优化空间,比如,size使用,能不能不使用size?不使用size又该如何实现?...另外,最近收到一些同学反馈,说哈希、哈希表、哈希函数他们之间有关系吗?有怎样关系?为什么Object要放一个hash()方法?跟equals()方法怎么又扯上关系了呢?

65020

Java WeakHashMap

做法肯定是想办法先知道某个Key肯定没有在用了,然后清理到HashMap对应K-V。...注意这里和HashMap不太一样地方,HashMap会在链表太长时候对链表做树化,把单链表转换为红黑树,防止极端情况下hashcode冲突导致性能问题,但在WeakHashMap没有树化。   ...WeakHashMapresize有另外一个额外操作,就是expungeStaleEntries(),就是对tab死对象做清理,稍后会详细介绍。...key,所以只要用indexFor定位到tab位置,然后遍历一下单链表就知道了。...这里也是整个WeakHashMap里唯一加了同步地方。   除了上文说到resize调用了expungeStaleEntries(),size()也调用了这个清理方法。

63620

迭代器

迭代器中断处理机制 迭代器是操作集合工具,当我们已经创建了一个迭代器之后,我们就不能再对原集合进行修改,否则可能报错出现问题 实际上迭代器对于中途修改集合操作给出了两个处理方式: fail-fast...: 集合出现修改情况,迭代器遍历直接报错 我们直接从底层方法讲起: /*Itr迭代器通常使用fail-fast中断处理机制*/ /*判断如何发生其他进程修改集合*/ private class...,并将snapshot元素复制进去,再将修改内容修改到新集合 同时COWIterator遍历旧集合,两者之间互不影响 */ } ArrayList 这里我们来介绍一下ArrayList...因为当hash较为随机时,hash表按破损分布,当负载因子为0.75时,长度超过8概率仅有亿分之六,这里是为了让树化几率足够小 /*hashCode问题*/ // 索引如何计算...1.在空间占用与查询时间之间取得较好平衡 2.大于这个数,空间节省了,但链表长度就会比较长从而影响性能 3.小于这个数,效率加快了,但扩容更加频繁,空间占用较多 /*

63540

如何保证容器是线程安全? ConcurrentHashMap 如何高效线程安全?

如何保证容器是线程安全?ConcurrentHashMap 如何高效线程安全? Java提供了不同层面的线程安全支持。...ConcurrentHashMap 是如何设计实现? ConcurrentHashMap 为什么能够大大提高并发效率?...重复扫描、检测冲突是 ConcurrentHash Map常见技巧在专栏上一讲介绍 HashMap时,提到了可能发生扩容问题,在 ConcurrentHashMap 同样存在。...不过有一个明显区别,就是它进行不是整体扩容,而是单独对 Segmen进行扩容,细节就不介绍了。 另外一个Mapsize方法同样需要关注,它实现涉及分离锁一个副作用。...实现相对简单,先找到哪个节点,然后,在链表遍历查找。

1.1K30
领券