HashMap集合: 底层是哈希表/散列表的数据结构

 HashMap集合:1、HashMap集合底层是哈希表/散列表的数据结构。2、哈希表是一个怎样的数据结构呢?哈希表是一个数组和单向链表的结合体。数组:在查询方面效率很高,随机增删方面效率很低。单向链表:在随机增删方面效率较高,在查询方面效率很低。哈希表将以上的两种数据结构融合在一起,充分发挥它们各自的优点。3、HashMap集合底层的源代码:public class HashMap{// HashMap底层实际上就是一个数组。(一维数组)Node<K,V>[] table;// 静态的内部类HashMap.Nodestatic class Node<K,V> {final int hash; // 哈希值(哈希值是key的hashCode()方法的执行结果。hash值通过哈希函数/算法,可以转换存储成数组的下标。)final K key; // 存储到Map集合中的那个keyV value; // 存储到Map集合中的那个valueNode<K,V> next; // 下一个节点的内存地址。}}哈希表/散列表:一维数组,这个数组中每一个元素是一个单向链表。(数组和链表的结合体。)4、最主要掌握的是:map.put(k,v)v = map.get(k)以上这两个方法的实现原理,是必须掌握的。5、HashMap集合的key部分特点:无序,不可重复。为什么无序? 因为不一定挂到哪个单向链表上。不可重复是怎么保证的? equals方法来保证HashMap集合的key不可重复。如果key重复了,value会覆盖。放在HashMap集合key部分的元素其实就是放到HashSet集合中了。所以HashSet集合中的元素也需要同时重写hashCode()+equals()方法。6、哈希表HashMap使用不当时无法发挥性能!假设将所有的hashCode()方法返回值固定为某个值,那么会导致底层哈希表变成了纯单向链表。这种情况我们成为:散列分布不均匀。什么是散列分布均匀?假设有100个元素,10个单向链表,那么每个单向链表上有10个节点,这是最好的,是散列分布均匀的。假设将所有的hashCode()方法返回值都设定为不一样的值,可以吗,有什么问题?不行,因为这样的话导致底层哈希表就成为一维数组了,没有链表的概念了。也是散列分布不均匀。散列分布均匀需要你重写hashCode()方法时有一定的技巧。7、重点:放在HashMap集合key部分的元素,以及放在HashSet集合中的元素,需要同时重写hashCode和equals方法。8、HashMap集合的默认初始化容量是16,默认加载因子是0.75这个默认加载因子是当HashMap集合底层数组的容量达到75%的时候,数组开始扩容。/*** The maximum capacity, used if a higher value is implicitly specified* by either of the constructors with arguments.* MUST be a power of two <= 1<<30.*/static final int MAXIMUM_CAPACITY = 1 << 30;重点,记住:HashMap集合初始化容量必须是2的倍数,这也是官方推荐的, 这是因为达到散列均匀,为了提高HashMap集合的存取效率,所必须的。




注意:同一个单向链表上所有的节点hosh相同,因为他们的数组下标是一样的。
但是同一个链表上的K和K的equals方法肯定返回的是false,都不相等 【无序不可重复】

package com.company.map;import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class HashMapTest {public static void main(String[] args) {// 测试HashMap集合key部分的元素特点// Integer是key,它的hashCode和equals都重写了。Map<Integer, String> map = new HashMap<>();map.put(1111, "zhangsan");map.put(6666, "lisi");map.put(7777, "wangwu");map.put(2222, "zhaoliu");map.put(2222, "king"); //key重复的时候value会自动覆盖。System.out.println(map.size()); // 4// 遍历Map集合Set<Map.Entry<Integer, String>> set = map.entrySet();for (Map.Entry<Integer, String> entry : set) {// 验证结果:HashMap集合key部分元素:无序不可重复。System.out.println(entry.getKey() + "=" + entry.getValue());}}
}

重写equals一定要重写hashcode:

package com.company.bean;import java.util.Objects;public class Student {private String name;public Student() {}public Student(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}// hashCode// equals(如果学生名字一样,表示同一个学生。)/*public boolean equals(Object obj){if(obj == null || !(obj instanceof Student)) return false;if(obj == this) return true;Student s = (Student)obj;return this.name.equals(s.name);}*/@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name);}}
package com.company.bean;import java.util.HashSet;
import java.util.Set;/**
1、向Map集合中存,以及从Map集合中取,都是先调用key的hashCode方法,然后再调用equals方法!
equals方法有可能调用,也有可能不调用。拿put(k,v)举例,什么时候equals不会调用?k.hashCode()方法返回哈希值,哈希值经过哈希算法转换成数组下标。数组下标位置上如果是null,equals不需要执行。拿get(k)举例,什么时候equals不会调用?k.hashCode()方法返回哈希值,哈希值经过哈希算法转换成数组下标。数组下标位置上如果是null,equals不需要执行。2、注意:如果一个类的equals方法重写了,那么hashCode()方法必须重写。
并且equals方法返回如果是true,hashCode()方法返回的值必须一样。equals方法返回true表示两个对象相同,在同一个单向链表上比较。那么对于同一个单向链表上的节点来说,他们的哈希值都是相同的。所以hashCode()方法的返回值也应该相同。3、hashCode()方法和equals()方法不用研究了,直接使用IDEA工具生成,但是这两个方法需要同时生成。4、终极结论:放在HashMap集合key部分的,以及放在HashSet集合中的元素,需要同时重写hashCode方法和equals方法。5、对于哈希表数据结构来说:如果o1和o2的hash值相同,一定是放到同一个单向链表上。当然如果o1和o2的hash值不同,但由于哈希算法执行结束之后转换的数组下标可能相同,此时会发生“哈希碰撞”。*/
public class HashMapTest02 {public static void main(String[] args) {Student s1 = new Student("zhangsan");Student s2 = new Student("zhangsan");// 重写equals方法之前是false//System.out.println(s1.equals(s2)); // false// 重写equals方法之后是trueSystem.out.println(s1.equals(s2)); //true (s1和s2表示相等)System.out.println("s1的hashCode=" + s1.hashCode()); //284720968 (重写hashCode之后-1432604525)System.out.println("s2的hashCode=" + s2.hashCode()); //122883338 (重写hashCode之后-1432604525)// s1.equals(s2)结果已经是true了,表示s1和s2是一样的,相同的,那么往HashSet集合中放的话,// 按说只能放进去1个。(HashSet集合特点:无序不可重复)Set<Student> students = new HashSet<>();students.add(s1);students.add(s2);System.out.println(students.size()); // 这个结果按说应该是1. 但是结果是2.显然不符合HashSet集合存储特点。怎么办?}
}

JDK1.8后

jdk1.8后HashMap中,如果哈希表单向链表中元素超过8个,单向链表会变成红黑树数据结构,当红黑树上的节点小于6时,会重新把红黑树变成单向链表数据结构

/*** The bin count threshold for using a tree rather than list for a* bin.  Bins are converted to trees when adding an element to a* bin with at least this many nodes. The value must be greater* than 2 and should be at least 8 to mesh with assumptions in* tree removal about conversion back to plain bins upon* shrinkage.*/
static final int TREEIFY_THRESHOLD = 8;/*** The bin count threshold for untreeifying a (split) bin during a* resize operation. Should be less than TREEIFY_THRESHOLD, and at* most 6 to mesh with shrinkage detection under removal.*/
static final int UNTREEIFY_THRESHOLD = 6;

红黑树:

HashMap底层数据结构相关推荐

  1. java 的HashMap底层数据结构

    HashMap也是我们使用非常多的Collection,它是基于哈希表的 Map 接口的实现,以key-value的形式存在.在HashMap中,key-value总是会当做一个整体来处理,系统会根据 ...

  2. 【Java基础】HashMap底层数据结构及其原理

    1.简单了解一下HashMap HashMap 就是以 Key-Value 键值对的方式进行数据存储的一种数据结构,它在 JDK 1.7 和 JDK 1.8 中底层数据结构是有些不一样的.简单来说,J ...

  3. 面试必备:HashMap底层数据结构?jdk1.8算法优化,hash冲突,扩容等问题

    面试必备系列不会长篇理论求证,直接上答案,仅供参考,不喜勿喷. 1.能说说HashMap的底层原理吗? HashMap<String,String> map = new HashMap&l ...

  4. hashmap底层原理_周末自己动手撸一个 HashMap,美滋滋

    对HashMap的思考 通过写一个迷你版的HashMap来深刻理解 定义接口 接口实现 看MyHashMap的构造 Entry 看put如何实现 hash函数 resize和rehash get实现 ...

  5. hashmap底层源码详解

    这里聊一下HashMap: HashMap底层数据结构: HashMap1.7之前数据结构是数组+链表 HashMap1.8之后数据结构加了红黑树(是用来处理hash冲突的) HashMap1.7之前 ...

  6. java集合听课笔记之hashMap的底层数据结构

    Map map中的key:无序,不可重复的 -->:key方法需要重写hashcode和equals方法 map中的value:无序,可重复的 一个键值对构成一个entry对象,entry对象无 ...

  7. hashmap的特性?HashMap底层源码,数据结构?Hashmap和hashtable ConcurrentHashMap区别?

    1.hashmap的特性? 允许空键和空值(但空键只有一个,且放在第一位) 元素是无序的,而且顺序会不定时改变 key 用 Set 存放,所以想做到 key 不允许重复,key 对应的类需要重写 ha ...

  8. Java集合- HashMap 的底层数据结构实现原理

    一.HashMap 的数据结构 JDK1.8 之前 JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列. HashMap 通过 key 的 hashCode 经过扰 ...

  9. Redis专题-底层数据结构与使用场景

    Redis介绍 Redis是一种基于键值对的NoSQL数据库,是一个基于内存中的数据结构存储系统,可以用作数据库.缓存和消息中间件.它支持以string(字符串),hash(哈希),list(列表), ...

  10. hashmap底层原理_Java集合 - HashMap原理(一) 概念和底层架构

    HashMap在Java开发中使用的非常频繁,可以说仅次于String,可以和ArrayList并驾齐驱,准备用几个章节来梳理一下HashMap.我们还是从定义一个HashMap开始. HashMap ...

最新文章

  1. 苹果和Siri的七年之痒:Siri的落寞之路
  2. commons fileUpload 文件上传下载
  3. MatLab GUI Load .mat File 导入mat文件
  4. 计算机端口封闭,如何查询局域网内被封的电脑端口?
  5. Java Zip压缩实现(亲测)
  6. python 字符串截取_Python 字符串操作实现代码(截取/替换/查找/分割)
  7. 判断两字符串是否为逆序
  8. 常量指针(指向常量的指针)和指针常量
  9. so运行出错:只包含了头文件,未同时编译cpp
  10. Linux ls按时间排列
  11. PCWorld:微软Google进军社交搜索需解决八问题
  12. 《软件开发的形式化方法-古天龙》笔记(1)
  13. 安卓电视盒子上 安装 Ubuntu 20.04 并安装 certbot 获取证书
  14. 手机整人脚本html,教大家用vbs代码制作恶搞整人
  15. Flash遮罩之溜光字制作一
  16. Python安装jpype,注意版本对应
  17. 2020伊始,电动车又给自己刷了一遍谎言buff
  18. 第三章 本地锁和分布式锁的区别
  19. 浏览器被恶意篡改(百分百成功)
  20. cherry 键盘WIN键不生效问题

热门文章

  1. ‘javah‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件
  2. 计算机网络实验——ns3仿真最短路由选择算法
  3. App自动化测试工具Airtest
  4. 红巨星粒子插件Trapcode Suite 14.0 Win版全套中文完美汉化版
  5. 虚幻引擎UE4源码编译安装(x86,arm64平台)
  6. CDA-LEVEL 1 数据分析师一级经验总结
  7. matlab散点图注释,MATLAB中散点图的绘制方法
  8. php简单排课_基于PHP+MYSOL教务排课系统的设计与实现.pdf
  9. Vue/vant——使用阿里巴巴矢量图引入图标
  10. java 二叉树详解 + 实现代码