hashmap

hashmap学习笔记

♀尐吖头ヾ 提交于 2020-03-08 13:21:41
最近开始在阅读一些源码之类的学习,趁着周末,今天详细学习了一些HashMap底层的知识,遂记录下来。有很多理解或者描述不当之处,望请指正。 ## 一、数据底层结构图 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190526213014826.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21pYW9wYXMx,size_16,color_FFFFFF,t_70) 首先放一张HashMap底层结构图,由于现在JDK几乎都用8及以上了,因此本文记录的都是基于JDK8的HashMap。 在JDK8以后,HashMap底层采用数组+链表+红黑树的形式来进行存储。 HashMap底层用一个数组来存放节点,节点在数组中的位置是由一个特殊的算法计算出来的(下文会提到)。如果两个节点计算出来的hash值相同,那么就将新的节点以链表的形式,连接在已存在的节点的后面。如果同一位置的节点数超过8个,那么会将链表改成红黑树的形式进行存储。 这样说有点抽象,结合源码一起看吧。 ## 二、HashMap源码解读 首先我们来看HashMap中的基本单位,节点,包括链表节点和红黑树节点。 链表节点: ``` /**

Java集合:Map接口总结

故事扮演 提交于 2020-03-08 11:12:06
一、HashMap 基于哈希表的 Map 接口的实现,允许存入 null 值和 null 键,无序存储且线程不同步; HashMap 初始容量默认为16,扩容一定是2的指数,加载因子默认值为0.75; HashMap采用Iterator方式迭代,可直接迭代键值对; 迭代 collection 视图所需的时间与 HashMap 实例的“容量”(桶的数量)及其大小(键-值映射关系数)成比例。所以,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。 建议多看源码,如果觉得晦涩可以戳 这里 看源码解析。 安利网址:http://www.admin10000.com/document/3322.html,个人觉得分析的挺好 JDK1.8+HashMap的改进 JDK1.8以前是采用的数组+链表形式存储,JDK1.8+是采用的是数组+链表/红黑树 JDK1.8+,当bucket节点数小于等于6时,转换为链表形式;当节点数大于等于8时,转换为红黑树形式 JDK1.8以前,HashMap的put()方法、get()源码如下: put(): public V put(K key, V value) { // HashMap允许存放null键和null值。 // 当key为null时,调用putForNullKey方法,将value放置在数组第一个位置。 if (key ==

HashMap,TreeMap,WeakHashMap,HashTable

自作多情 提交于 2020-03-08 11:10:02
1,HashMap hashmap数据结构为一个hash表,具体的代码实现就是一个数组,每个数据里面存放一个链表,初始化的时候默认的数组大小为16,负载因子为0.75(这个值可以保证碰撞最低并且空间利用率最高),当元素的个数大于(负载因子*数组长度)的时候,会进行数组扩容,扩大为2倍(所以当内存比较吃紧的时候,可以适当地增加负载因子,当内存很充足的时候,可以减少负载因子)。前面的叙述是针对jdk7及以下版本的,jdk8的hashmap稍稍做了一些改变,就是当数组中的链表达到一定的阈值的时候,这个链表会转化成一颗红黑树,这个优势就很明显了,在红黑树里面查询一个数据可比在链表中查询效率高多了。 2,TreeMap 可以说不论是添加操作,还是查找操作,treeMap的效率都没有hashMap高,因为在操作之前他们都是需要定位的,而hashMap只需要算出hash值就可以找到相应的数组小标,从而定位到相应的位置,而treemap是需要从树的顶端往下寻找,时间复杂度为log(n),那这个treemap的价值是什么呢?别忘了treemap实现了一个接口叫做SortedMap,也就说treemap是一个有序的map,当你需要按顺序输出一组数据的时候就可以选择treemap了。 treemap的内部数据结构是红黑树(R-B Tree)

HashMap和TreeMap

谁说胖子不能爱 提交于 2020-03-08 11:06:18
hashMap HashMap工作原理 我对hashMap的认识基本是对的,hashCode() and equals() is important for hashMap. 除了这个完全不知道 当重新调整HashMap大小的时候,确实存在条件竞争,因为如果两个线程都发现HashMap需要重新调整大小了,它们会同时试着调整大小。在调整大小的过程中,存储在链表中的元素的次序会反过来,因为移动到新的bucket位置的时候,HashMap并不会将元素放在链表的尾部,而是放在头部,这是为了避免尾部遍历(tail traversing)。如果条件竞争发生了,那么就死循环了。这个时候,你可以质问面试官,为什么这么奇怪,要在多线程的环境下使用HashMap呢?:) TreeMap TreeMap is base on RB-Tree. 如果键值没有实现java.lang.Comparable是真的不行的。。。 A Red-Black tree based NavigableMap implementation. The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which

二、容器

安稳与你 提交于 2020-03-07 19:56:43
java容器有哪些 数组、String(底层是char数组)、java.util下 的 List、Set、Map、Queue,画图说明如下: Collection和Collections有什么区别 Collection为集合的通用接口,提供了对集合进行操作的通用接口方法 Collections为集合操作的工具类,提供了集合的静态操作方法,不能实力化 List、set、Map之间的区别是什么 三个集合操作的不同 HashMap和HashTable有什么区别 HashMap:线程不安全,效率高;key和value可以为空 HashTable:线程安排,效率低;key和value都不能为空 如何决定使用HashMap还是TreeMap HashMap不支持排序,查询效率高;TreeMap默认用key排序,也支持自定义排序,查询效率低;如无排序要求,尽量使用HashMap HashMap的实现原理 利用key的hashCode重新hash计算出当前对象的元素在数组中的下标 存储时,如果没有该hash值得key,则放入;如果出现hash值相同的key,此时有两种情况。(1)如果key相同,则覆盖原始值;(2)如果key不同(出现冲突),则将当前的key-value放入链表中 获取时,直接找到hash值对应的下标,在进一步判断key是否相同,如果相同,取出该值;如果不同,从链表中找对应值。

ConcurrentHashMap 的实现原理

若如初见. 提交于 2020-03-07 08:57:19
概述 我们在之前的博文中了解到关于 HashMap 和 Hashtable 这两种集合。其中 HashMap 是非线程安全的,当我们只有一个线程在使用 HashMap 的时候,自然不会有问题,但如果涉及到多个线程,并且有读有写的过程中,HashMap 就不能满足我们的需要了(fail-fast)。在不考虑性能问题的时候,我们的解决方案有 Hashtable 或者Collections.synchronizedMap(hashMap),这两种方式基本都是对整个 hash 表结构做锁定操作的,这样在锁表的期间,别的线程就需要等待了,无疑性能不高。 所以我们在本文中学习一个 util.concurrent 包的重要成员,ConcurrentHashMap。 ConcurrentHashMap 的实现是依赖于 Java 内存模型,所以我们在了解 ConcurrentHashMap 的前提是必须了解Java 内存模型。但 Java 内存模型并不是本文的重点,所以我假设读者已经对 Java 内存模型有所了解。 ConcurrentHashMap 分析 ConcurrentHashMap 的结构是比较复杂的,都深究去本质,其实也就是数组和链表而已。我们由浅入深慢慢的分析其结构。 先简单分析一下,ConcurrentHashMap 的成员变量中,包含了一个 Segment 的数组( final

alicode45-最活跃的数

≯℡__Kan透↙ 提交于 2020-03-07 06:55:25
1 package solution45; 2 import java.util.*; 3 class Solution { 4 public int solution(int n, int[] nums) { 5 HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); 6 int maxVal = 0; 7 for (int i = 0; i < n; i++) { 8 int cur = nums[i]; 9 for (int j = -1; j <= 1; j++) { 10 int val = cur + j; 11 if (!map.containsKey(val)) { 12 map.put(val, 1); 13 maxVal = Math.max(maxVal, 1); 14 } else { 15 int newval = map.get(val) + 1; 16 map.put(val, newval); 17 maxVal = Math.max(maxVal, newval); 18 } 19 } 20 } 21 return maxVal; 22 } 23 } 算法思路:hash。 来源: https://www.cnblogs.com/asenyang/p/12432422.html

java基础进阶篇(六)------HashTable

孤街浪徒 提交于 2020-03-06 11:02:17
文章目录 一.概述 二.和HashMap的比较 1.不同点 1).接口 2).线程安全 3).初始容量和扩容 4).键值null 的情况 2.相同点 三.结构图 一.概述   前面介绍了HashMap的结构和原理,这里介绍个类似HashMap的结构Hashtable。   HashTable 官方解释是HashMap的轻量级实现, 和 HashMap 一样,Hashtable 也是一个 散列表 ,它存储的内容是 键值对(key-value)映射 。   所以我们结合HashMap来介绍HashTable, 比较下两者的区别。   HashTable 使用的很少, 它支持线程安全, 通过内部方法加上 synchronized 实现, 因此同步锁的密度太大了, 在实际情况中笔者用的很少, 所以关于方法就不像HashMap 详细介绍了.后面会单独准备一章解决HashMap的线程同步问题. 二.和HashMap的比较 1.不同点 1).接口    Hashtable 继承于Dictionary,实现了Map、Cloneable、java.io.Serializable接口。   HashMap继承AbstractMap,实现了Map, Cloneable, Serializable接口。 2).线程安全    Hashtable 线程安全,支持多线程并发,

java基础进阶篇(七)_LinkedHashMap------【java源码栈】

别说谁变了你拦得住时间么 提交于 2020-03-06 10:31:21
目录 一.概述 二.特点 三.应用场合 四.构造方法 1.参数为空 2.accessOrder 五.源码结构分析 六.常见问题 1.如何实现的元素有序? 2.如何保证顺序的正确以及同步 3.如何实现两种顺序(插入顺序或者访问顺序)? 4.为什么重写containsValue()而不重写containsKey()? 七.常用方法 一.概述   LinkedHashMap是HashMap的子类,关于HashMap可以看下前面的章节: java基础进阶篇 HashMap public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> 二.特点 非线程安全 LinkedHashMap 内部保证顺序; 分插入顺序和访问排序两种, 如果是访问顺序,那put和get操作已存在的Entry时,都会把Entry移动到双向链表的表尾(其实是先删除再插入)。 HashMap不保证插入顺序. LinkedHashMap存取数据,还是跟HashMap一样使用的Entry[]的方式,双向链表只是为了保证顺序。 LinkedHashMap是继承于HashMap,是基于HashMap和双向链表来实现的。 LinkedHashMap的插入顺序和访问顺序可以由开发者自己决定. 三.应用场合   HashMap是无序的,当我们希望有顺序(

HashSet与HashMap的区别

孤者浪人 提交于 2020-03-06 05:57:52
面试中经常被问到HashMap与HashSet的区别。于是本渣静下心来总结了一下HashSet与HashMap的区别。   先了解一下HashMap跟HashSet HashSet:    HashSet实现了Set接口,它不允许集合中出现重复元素。当我们提到HashSet时,第一件事就是在将对象存储在 HashSet之前,要确保重写hashCode()方法和equals()方法,这样才能比较对象的值是否相等,确保集合中没有 储存相同的对象。如果不重写上述两个方法,那么将使用下面方法默认实现:  public boolean add(Object obj)方法用在Set添加元素时,如果元素值重复时返回 "false",如果添加成功则返回"true" HashMap:    HashMap实现了Map接口,Map接口对键值对进行映射。Map中不允许出现重复的键(Key)。Map接口有两个基本的实现 TreeMap和HashMap。TreeMap保存了对象的排列次序,而HashMap不能。HashMap可以有空的键值对(Key(null)-Value(null)) HashMap是非线程安全的(非Synchronize),要想实现线程安全,那么需要调用collections类的静态方法synchronizeMap()实现。 public Object put(Object Key