hashmap

带你逐行分析 HashMap 源码

邮差的信 提交于 2020-02-26 23:46:23
带你逐行分析 HashMap 源码 一、写在前面 相信读者也看过了不少讲解 HashMap 源码的文章了,笔者认为,一切脱离源码去讲原理的都是泛泛而谈。一些所谓的原理大都是阅读源码之后的个人概括,这些概括参差不齐,再加上没有阅读源码,读者们是很难有切身体会的。正因如此,笔者逐行分析了 HashMap 的源码后,开启了本场 Chat。 笔者在阅读 HashMap 源码的时候,曾对每个内部属性,每个内部方法和方法调用逻辑做了简要注释,但在整理成文的时候,还是遇到了略微的困难。对于一些内部属性的解释,需要结合它在一些方法的使用中发挥的作用来综合说明,笔者打算按照从浅到深的顺序,先带读者熟悉 HashMap 的宏观设计思想,再通读一遍源码,然后讲解源码的设计细节。要让读者边看文字边对照源码进行学习,形成自己的领悟和体会,避免造成笔者一人的泛泛而谈。 无论自己的领悟是深是浅,终归是自己的,无论别人的领悟多么高深,那也是别人的。希望每个读者都能有自己的收获和体会。 Java 版本 $ java -version java version "1.8.0\_211" Java(TM) SE Runtime Environment (build 1.8.0\_211-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed

hashmap与currentHashMap

时间秒杀一切 提交于 2020-02-26 18:39:10
hashmap的缺点 多线程不安全,在并发场景下使用时容易出现死循环,脏读问题等 死循环: https://juejin.im/post/5a66a08d5188253dc3321da0 (这篇好点) https://blog.csdn.net/justloveyou_/article/details/72783008 脏读: https://blog.csdn.net/qq_33591903/article/details/81672260 currrntHashMap的改进 由于扩容是按照2的幂次方进行的,所以扩展前在同一个桶中的元素,现在要么还是在原来的序号的桶里,或者就是原来的序号再加上一个2的幂次方,就这两种选择。 其中抛弃了JDK1.7的 Segment 分段锁,而采用了 CAS + synchronized 来保证并发安全性。 CAS与synchronized : https://juejin.im/post/5c37377351882525ec200f9e CAS(乐观锁)比synchronized(悲观锁)轻量级一点,消耗的资源比较小。 CAS 是 compare and swap 的简写,即比较并交换。它是指一种操作机制,而不是某个具体的类或方法。在 Java 平台上对这种操作进行了包装。在 Unsafe 类中,调用代码如下: unsafe

Hashmap 扩容

谁说我不能喝 提交于 2020-02-26 14:42:17
一、hashmap的数据结构 要知道hashmap是什么,首先要搞清楚它的数据结构,在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,hashmap也不例外。Hashmap实际上是一个数组和链表的结合体(在数据结构中,一般称之为“链表散列“),请看下图(横排表示数组,纵排表示数组元素【实际上是一个链表】)。 从图中我们可以看到一个hashmap就是一个数组结构,当新建一个hashmap的时候,就会初始化一个数组。我们来看看java代码: Java代码 /** * The table, resized as necessary. Length MUST Always be a power of two. * FIXME 这里需要注意这句话,至于原因后面会讲到 */ ransient Entry[] table; static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; final int hash; Entry<K,V> next; .......... } 上面的Entry就是数组中的元素,它持有一个指向下一个元素的引用,这就构成了链表。 当我们往hashmap中put元素的时候

100+经典Java面试题及答案解析

情到浓时终转凉″ 提交于 2020-02-26 09:59:53
面向对象编程(OOP) Java是一个支持并发、基于类和面向对象的计算机编程语言。下面列出了面向对象软件开发的优点: 代码开发模块化,更易维护和修改。 代码复用。 增强代码的可靠性和灵活性。 增加代码的可理解性。 面向对象编程有很多重要的特性,比如:封装,继承,多态和抽象。下面的章节我们会逐个分析这些特性。 封装 封装给对象提供了隐藏内部特性和行为的能力。对象提供一些能被其他对象访问的方法来改变它内部的数据。在Java当中,有3种修饰符:public,private和protected。每一种修饰符给其他的位于同一个包或者不同包下面对象赋予了不同的访问权限。 下面列出了使用封装的一些好处: 通过隐藏对象的属性来保护对象内部的状态。 提高了代码的可用性和可维护性,因为对象的行为可以被单独的改变或者是扩展。 禁止对象之间的不良交互提高模块化。 参考这个文档获取更多关于封装的细节和示例。 多态 多态是编程语言给不同的底层数据类型做相同的接口展示的一种能力。一个多态类型上的操作可以应用到其他类型的值上面。 继承 继承给对象提供了从基类获取字段和方法的能力。继承提供了代码的重用行,也可以在不修改类的情况下给现存的类添加新特性。 抽象 抽象是把想法从具体的实例中分离出来的步骤,因此,要根据他们的功能而不是实现细节来创建类。Java支持创建只暴漏接口而不包含方法实现的抽象的类

Spring+SpringMVC+MyBatis深入学习及搭建(四)——MyBatis输入映射与输出映射(转发同上)

社会主义新天地 提交于 2020-02-26 04:31:59
原地址:http://www.cnblogs.com/shanheyongmu/p/7121556.html 1. 输入映射 通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型。 1.1 #{}与${} #{}实现的是向prepareStatement中的预处理语句设置参数值,sql语句中#{}表示一个占位符即? <select id="findUserById" parameterType="int" resultType="user"> select * from user where id=#{id} </select> 使用占位符#{}可以有效防止sql注入,在使用时不需要关系参数值的类型,mybatis会自动进行java类型和jdbc类型的转换。#{}可以接收简单类型值或pojo属性值,如果parameterType传输单个类型值,#{}括号可以是value或其它名称。 ${}和#{}不同,通过${}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。使用${}不能防止sql注入,但是有时用${}会非常方便,如下例子: <select id=

程序员悲催瞬间:来之不易的美团面试,竟然挂了(还原真实场景)

老子叫甜甜 提交于 2020-02-26 02:36:39
一面 1、自我介绍 答:自我介绍是面试中唯一的自己主动介绍自己的环节,一定要好好把握好,你数据结构学的号可以手撕一个红黑树你就说我数据结构掌握地很好,反正就是要把自己的优势凸显出来,比如自己对于java的知识较熟悉,我介绍完自己的本科经历以后,我就说我是保送到本校继续读研究生,然后最末尾会加上自己熟悉java,然后面试官就会问java的一些东西; 2、项目介绍及其亮点 答:使劲吹... 3、java的8种数据类型有哪些? 答:感觉这个问题被问烂了,int,short,long,float,double,byte,boolean,char; 4、问了Integer缓存数据的范围? 答:-128-127 5、紧接着问了Object类有哪些方法? 答:这个我有背过,clone,getClass,toString,finalize,equals,hashCode,wait,notify,notifyALL。(不懂面试这个什么意思) 6、问到这里然后拿出了一个题,面试官有小纸条,题目在上面,String A = "123"; String B = new String("123");,问我生成了几个String对象? 答:我说如果常量池中,原来没有“123”那么就是生成了2个对象,如果常量池中有“123”那么只要1个对象生成(面试官别问这种问题了) 7、由于提到了wait

都说知道 HashMap 线程不安全,那它为啥就不安全?

倖福魔咒の 提交于 2020-02-26 01:17:08
我们都知道HashMap是线程不安全的,在多线程环境中不建议使用,但是其线程不安全主要体现在什么地方呢,本文将对该问题进行解密。 1.jdk1.7中的HashMap 在jdk1.8中对HashMap做了很多优化,这里先分析在jdk1.7中的问题,相信大家都知道在jdk1.7多线程环境下HashMap容易出现死循环,这里我们先用代码来模拟出现死循环的情况: public static void main(String[] args) { HashMapThread thread0 = new HashMapThread(); HashMapThread thread1 = new HashMapThread(); HashMapThread thread2 = new HashMapThread(); HashMapThread thread3 = new HashMapThread(); HashMapThread thread4 = new HashMapThread(); thread0.start(); thread1.start(); thread2.start(); thread3.start(); thread4.start(); } } class HashMapThread extends Thread { private static AtomicInteger

HashMap,Hashtable,ConcurrentHashMap 和 synchronized Map 的原理和区别

ぐ巨炮叔叔 提交于 2020-02-26 00:00:26
HashMap 是否是线程安全的,如何在线程安全的前提下使用 HashMap,其实也就是 HashMap , Hashtable , ConcurrentHashMap 和 synchronized Map 的原理和区别。当时有些紧张只是简单说了下HashMap不是线程安全的;Hashtable 线程安全,但效率低,因为是 Hashtable 是使用 synchronized 的,所有线程竞争同一把锁;而 ConcurrentHashMap 不仅线程安全而且效率高,因为它包含一个 segment 数组,将数据分段存储,给每一段数据配一把锁,也就是所谓的锁分段技术。当时忘记了 synchronized Map 和解释一下 HashMap 为什么线程不安全。面试结束后问了下面试官哪里有些不足,面试官说上面这个问题的回答算过关,但可以在深入一些或者自己动手尝试一下。so~~~虽然拿到了 offer,但还是再整理一下,不能得过且过啊。 为什么HashMap是线程不安全的 总说 HashMap 是线程不安全的,不安全的,不安全的,那么到底为什么它是线程不安全的呢?要回答这个问题就要先来简单了解一下 HashMap 源码中的使用的 存储结构 (这里引用的是 Java 8 的源码,与7是不一样的)和它的 扩容机制 。 HashMap的内部存储结构 下面是 HashMap 使用的存储结构: 1 2

== 和 equals,equals 与 hashcode,HashSet 和 HashMap,HashMap 和 Hashtable

好久不见. 提交于 2020-02-25 23:47:08
一:== 和 equals == 比较引用的地址 equals 比较引用的内容 (Object 类本身除外) String obj1 = new String("xyz"); String obj2 = new String("xyz"); // If String obj2 = obj1, the output will be true if(obj1 == obj2) System.out.printlln("obj1==obj2 is TRUE"); else System.out.println("obj1==obj2 is FALSE"); // It will print obj1==obj2 is False // If String obj2 = obj1, the output will be true 默认的, equals() 方法实际上和 “==” 在 object 类里是一样的. 但是这个方法在每一个子类里都 会被覆写用来比较引用的内容 (因为每个类都继承了 object 类并覆写了这个方法) String obj1 = new String("xyz"); String obj2 = new String("xyz"); if(obj1.equals(obj2)) System.out.printlln("obj1==obj2 is TRUE");

Map and HashMap

浪尽此生 提交于 2020-02-25 23:44:12
1.1.1. Map 接口 java提供了一组可以以键值对(key-value)的形式存储数据的数据结构,这种数据结构称为Map。我们可以把Map看成一个多行两列的表格,其中第一列存放key,第二列存放value。 而每一行就相当于一组key-value对,表示一组数据。 Map对存入的元素有一个要求,就是key不能重复,所谓不能重复指的是在Map中不能包含两个equals为true的key。 Map对于key,value的类型没有严格要求,只要是引用类型均可。但是为了保证在使用时不会造成数据混乱,通常我们会使用泛型去约束key与value的类型。 1.1.2. put方法 既然我们知道了Map在保存数据时实际上是存入了两部分信息的 ,key与value。那么我们来看看如何向Map中存入数据。 Map提供了一个方法: V put ( K k , V v ) 该方法的作用是将key-value对存入Map中,因为Map中不允许出现重复的key,所以若当次存入的key已经在Map中存在,则是替换value操作,而返回值则为被替换的元素。若此key不存在,那么返回值为null。 1.1.3. get方法 我们学会了如何向Map中存入数据,那么我们再来看看如何获取数据。Map中获取数据的方式是给定Key获取对应的Value。 Map提供了一个方法: V get ( Object key )