关于HashMap--个人学习记录

说说 Java 中 HashMap 的原理?

HashMap底层在1.7是数组+链表 在1.8后是数组+链表+红黑树

具体而言对于 put(key,value)操作来说 我们会计算出key的哈希值 然后通过数组长度-1 && key 计算出该存储的下标位置如果 如果说发现该下标有了数据了 那么代表此时发生了哈希冲突 对于put操作来说会将其依次匹配该下标位置的链表元素 如果说equals(key)相同就将value覆盖 如果遍历完了链表还没有相同的key 就插入到链表尾节点

对于扩容机制来说 如果说数组的大小达到了负载因子 也就是0.75 那么此时就会将数组大小翻倍里面的元素进行重新计算放到新数组当中 称为rehash

Java 中 ConcurrentHashMap 1.7 和 1.8 之间有哪些区别?

1.7的时候核心思想是采取分段锁 每个 Segment 内部维护一个 HashEntry<K,V>[] table 数组,相当于一个小的 HashMap segment继承ReentranLock 不同线程访问不同的段 互相之间不影响 每次都会锁住整个segment桶数组 + 其下的所有链表

对于1.8来说 锁的颗粒度更精细了 锁细化到每个槽位 每次插入的时候如果下标位置没有节点先通过CAS插入新的节点 如果有节点通过synchronized将这个节点上锁 执行后续操作 别的线程就无法访问这个节点以及后面的链表 或 红黑树了 每次锁住的都是头节点synchronized(头节点)

为什么 JDK 1.8 对 HashMap 进行了红黑树的改动?

因为HashMap 1.7以及之前 如果说冲突过多链表过长 就会从o(1) 退化到 o(n) 所以1.8在链表长度大于8并且数组长度大于64的时候转换为红黑树 如果说数组长度较低的话本身hash冲突就比较激烈所以规定了必须要数组长度大于64才可以

JDK 1.8 对 HashMap 除了红黑树还进行了哪些改动?

1.7使用的是头插法 1.8后使用尾插法 因为头插法会有循环链表的问题

对于扩容机制来说也是同理 JDK 1.7 :扩容后,每个元素必须调用函数重新计算在新数组中的下标位置。

对于1.8来话说利用了2的幂次方的特性 扩容后小标只有两种可能 意识原位置 二是 一道道原位置加旧数组长度 低位保持不变 高位集体搬家

Java 中有哪些集合类?请简单介绍

List 有序可重复 按照下标访问 ArrayList底层是数组 增删较慢但是查询较快 LinkedList底层是链表增删较快但是查询较慢 不过也是增删较快也是针对于头节点和尾节点来说

Set set是不允许有重复元素 HashSet基于哈希表 key用来存储元素 value存储固定值 LinkedHashSet用链表维护顺序 TreeSet基于红黑树 元素按大小排序

Map HashMap基于哈希表键 LinkedHashMap 底层基于哈希表和双向链表 维护了插入顺序和存储顺序一致 HashMap在并发编程下线程有问题ConcurrentHashMap则是更好的选择

相关推荐
SamDeepThinking10 分钟前
裁掉那个差程序员后,给你看团队里高手的代码:这个习惯,希望你有
java·后端·程序员
朕瞧着你甚好1 小时前
技术雷达 & Java 集成评估报告 — Apache Tika 3.3.1
java·ai编程
MacroZheng2 小时前
短短几天,暴涨2.8万Star!又一款编程神器开源!
java·人工智能·后端
SamDeepThinking2 小时前
函数式编程:用BiFunction消除多类型分支的代码重复
java·后端·面试
Flittly20 小时前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
小兔崽子去哪了20 小时前
Java 生成二维码解决方案
java·后端
人活一口气1 天前
从JVM调优到MCP协议:Java全栈技术体系深度总结与企业级架构实践
java·spring boot
NE_STOP1 天前
Vibe Coding -- 完整项目案例实操
java
荣码1 天前
GraphRAG:普通RAG只能回答"点"的问题,我踩了4个坑才搞懂
java·python
SimonKing1 天前
Google第三方授权登录
java·后端·程序员