hashmap

[转载] HashMap的工作原理-hashcode和equals的区别

落花浮王杯 提交于 2020-02-17 20:08:31
目录 前言 为什么需要使用Hashcode,可以从Java集合的常用需求来描述: 更深入的介绍 先来些简单的问题 HashMap的0.75负载因子 总结 我在网上看到的这篇文章,介绍的很不错,但是我看的那篇文章也是转载的,我也不知道原作者是谁,只能注明我是转载的 前言 首先再次强调hashcode (==)和equals的真正含义(我记得以前有人会说,equals是判断对象内容,hashcode是判断是否相等之类): equals:是否同一个对象实例。注意,是“实例”。比如String s = new String(“test”); s.equals(s), 这就是同一个对象实例的比较; 等号(==):对比对象实例的内存地址(也即对象实例的ID),来判断是否是同一对象实例;又可以说是判断对象实例是否物理相等; Hashcode:我觉得可以这样理解:并不是对象的内存地址,而是利用hash算法,对对象实例的一种描述符(或者说对象存储位置的hash算法映射)——对象实例的哈希码。 为什么需要使用Hashcode,可以从Java集合的常用需求来描述: Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。那么这里就有一个比较严重的问题了:要想保证元素不重复

如何线程安全的使用HashMap

雨燕双飞 提交于 2020-02-17 14:20:13
HashMap: 线程不安全,链表结构,效率高; Hashtable : 线程安全,但效率低,因为是Hashtable是使用synchronized的,所有线程竞争同一把锁; Synchronized Map: 线程安全,但效率低,一次性锁住整张表来保证线程安全,所以每次只能有一个线程来访问map。 ConcurrentHashMap:线程安全而且效率高,因为它包含一个segment数组,将数据分段存储,给每一段数据配一把锁。           在理想状态下,ConcurrentHashMap 可支持16个线程执行并发写操作,及任意数量线程的读操作。 如何线程安全的使用HashMap : 以下三种方式: Hashtable ConcurrentHashMap Synchronized Map    来源: https://www.cnblogs.com/lgg20/p/12321427.html

HashMap和ConcurrentHashMap的原理和实现

微笑、不失礼 提交于 2020-02-16 18:33:31
一.线程不安全的HashMap 多线程环境下,使用HashMap进行put操作会引起死循环(jdk1.7 Entry链表形成环形数据结构),导致CPU利用率接近100%。 结构:数组 table[]+链表entry<k,v> put 对key做hash 默认初始化数组长度 16 加载因子 0.75 扩容 大于16*0.75时 rehash hash冲突:链表解决。原来的entry移出去,后来的进来,然后next指向原来的entry 线程不安全:多个线程扩容时闭环,引起死循环。 为什么会形成闭环: 线程1 A>B>C 线程2 B>A倒置。会变成A>B>A 解决: 1.8 红黑树:数组+链表+红黑树。阈值:8 hashmap扩容过程: 传入新的容量 初始化新的Entry数组,将数据转移到新的Entry数组里(遍历旧数组,取得每个元素,释放旧数组的引用,重新计算位置) table属性引用新的entry数组 修改阈值 hash算法:取key的hashcode值,高位运算,取模运算 1.8的优化 1.resize时不需要重新计算hash,只要看看原来的hash新增的那个bit是0还是1。0的话索引没变,1的话索引变成原索引加oldcap。找到新数组下标,确定索引位置,增加随机性。 2.不会形成闭环,扩容时不再使用头插法改成尾插法。 二.效率低下的HashTable

Java_Map集合接口

♀尐吖头ヾ 提交于 2020-02-16 10:02:31
现实生活中,我们经常需要成对存储某些信息。比如,我们使用的微信,一个手机号只能对应一个微信账户。这就是一种成对存储的关系。 Map就是用来存储“键(key)-值(value) 对”的。 Map类中存储的“键值对”通过键来标识,所以“键对象”不能重复。 Map 接口的实现类有HashMap、TreeMap、HashTable、Properties等。 Map接口中常用的方法: HashMap采用哈希算法实现,是Map接口最常用的实现类。 由于底层采用了哈希表存储数据,我们要求键不能重复,如果发生重复,新的键值对会替换旧的键值对。 HashMap在查找、删除、修改方面都有非常高的效率。 Map接口中的常用方法 : import java.util.HashMap; import java.util.Map; public class TestMap { public static void main(String[] args) { Map<Integer, String> m1 = new HashMap<Integer, String>(); Map<Integer, String> m2 = new HashMap<Integer, String>(); m1.put(1, "张三"); m1.put(2, "李四"); m1.put(3, "王五"); m2.put(1, "一

javaSE学习笔记(11)--- Map

淺唱寂寞╮ 提交于 2020-02-12 23:48:49
javaSE学习笔记(11)--- Map 1、Map集合 现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对象,即 java.util.Map 接口。 我们通过查看 Map 接口描述,发现 Map 接口下的集合与 Collection 接口下的集合,它们存储数据的形式不同,如下图。 Collection 中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。 Map 中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。 Collection 中的集合称为单列集合, Map 中的集合称为双列集合。 需要注意的是, Map 中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。 Map常用子类 通过查看Map接口描述,看到Map有多个子类,这里我们主要讲解常用的HashMap集合、LinkedHashMap集合。 HashMap<K,V> :存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。 LinkedHashMap<K,V> :HashMap下有个子类LinkedHashMap

Java集合常见面试题

江枫思渺然 提交于 2020-02-12 02:36:28
适可而止,见好就收 来源主要是 牛客 的Java实习面经。下面的回答直接背就可以,需要一定的Java基础,适合春招实习的同学,但是我会在每个问题下把有助于理解的博客贴出来。如果发现有问题欢迎私聊我或留言我会在下面更新 Map 1. Map的底层结构 腾讯19年秋招 这个题乍一看没有什么思路(因为Map是个集合,当然也有可能是我记错了),所以我们可以先介绍一下Map然后转到HashMap中 Map是一种使用键值对存储的集合。Map会维护与Key有关联的值。两个Key可以引用相同的对象,但Key不能重复,典型的Key是String类型,但也可以是任何对象。 在整个Map系列中,AbstractMap抽象类实现了Map,SortedMap接口继承了Map。而我们常用的HashMap,HashTable,TreeMap和ConcurrentHashMap有继承了AbstractMap类。 其中,HashTable和ConcurrentHashMap是线程安全的。前者是通过synchronized实现的,后者是通过AQS实现的。其中要注意HashTable不能存空值,HashMap是线程不安全的,key可以为空。TreeMap通过二叉树算法实现有序集合,它实现了SortedMap接口 2. HashMap的原理 阿里17年实习,小米19年秋招本科,滴滴19年秋招本科,网易19年秋招本科

HashMap HashTable ConcurrentHashMap

偶尔善良 提交于 2020-02-11 14:22:20
1. Hashtable 和 HashMap (1)区别,这两个类主要有以下几方面的不同: Hashtable和HashMap都实现了Map接口,但是Hashtable的实现是基于Dictionary抽象类。 在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。 当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。 因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。 而在Hashtable中,无论是key还是value都不能为null 。 这两个类最大的不同在于: (1)Hashtable是线程安全的,它的方法是同步了的,可以直接用在多线程环境中。 (2)而HashMap则不是线程安全的。在多线程环境中,需要手动实现同步机制。 因此,在Collections类中提供了一个方法返回一个同步版本的HashMap用于多线程的环境: Java代码 public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) { return new SynchronizedMap<K,V>(m); } 该方法返回的是一个SynchronizedMap 的实例。

HashMap、HashTable、ConcurrentHashMap的区别

我的未来我决定 提交于 2020-02-11 14:18:55
一、相关概念 1、Map的概念 javadoc中对Map的解释如下: An objectthat maps keys to values . Amap cannot contain duplicatekeys; each key can map to at most one value. This interface takes the place of the Dictionary class, which was atotally abstract class rather than an interface. The Map interface provides three collection views, which allow amap's contents to be viewed as a set of keys, collection of values,or set of key-value mappings. 从上可知,Map用于存储“key-value”元素对,它将一个key映射到一个而且只能是唯一的一个value。 Map可以使用多种实现方式,HashMap的实现采用的是hash表;而TreeMap采用的是红黑树。 2、HashMap 实现了Map接口,实现了将唯一键隐射到特定值上。 允许一个NULL键和多个NULL值。非线程安全。 3、HashTable

ConcurrentHashMap 1.7/1.8比较

此生再无相见时 提交于 2020-02-10 19:04:10
ConcurrentHashMap JDK7中的实现 1.1 设计思路 1.2 并发度(Concurrency Level) 1.3 创建分段锁 1.4 put/putIfAbsent/putAll 1.5 rehash 1.6 remove 1.7 get与containsKey 1.8 size、containsValue JDK8中的实现 2.1 重要的类 2.2.1 Node 2.2.2 TreeNode 2.2.3 TreeBin 2.2.4 ForwardingNode 2.3 Unsafe与CAS 2.3.1 unsafe静态块 2.3.2 三个核心方法 2.4 初始化方法initTable 2.5 扩容方法 transfer 2.6 Put方法 2.6.1 helpTransfer方法 2.6.2 treeifyBin方法 2.7 get方法 总结 java容器可参见: 集合底层实现原理   并发编程实践中,相比于Hashtable以及Collections.synchronizedMap(),ConcurrentHashMap在线程安全的基础上提供了更好的写并发能力,但同时降低了对读一致性的要求。ConcurrentHashMap大量运用volatile,final,CAS等lock-free技术来减少锁竞争对于性能的影响。 JDK7中的实现 1.1 设计思路  

Java8新特性之引导篇----为什么速度更快

我与影子孤独终老i 提交于 2020-02-10 17:33:26
为什么要学习java8新特性? 简单而言就是使一个程序员的代码更加简洁高效,这也是语言发展的必然性,当然我这样说太笼统了,所以我特意去网上找了一张图,相信这张图就很能说明问题了。 何来速度更快? 为什么说java8速度更快呢?因为它对底层的数据结构做了改动,对垃圾回收机制(内存结构)做了改变,对并行做了一个扩展和支持,当然还有一些小的改动就不一一例举了。 数据结构的改变 最典型的就是HashMap,说到它就不得不说一下哈希表了,相信作为程序员大部分应该都知道,HashMap底层其实就是一个链表,说白了就是类似于一个数组+链表的结构(当然它还多了其它东西,嘿嘿,想知道你就得去看看HashMap详解了),然后根据索引来放你想存放的东西,而这个索引是怎么产生的呢,就是通过哈希算法产生的,所以说这一下就提高了多少的运算效率呢,如果没有它,你要放一个新元素去这个数组中,它就需要和数组中已经存在的每一个元素进行一次比较,但有了哈希表后,你每次放一个新元素,只需要计算这个新元素的哈希值,然后通过哈希值找到这个数组的索引,然后往这索引的位置插入就可以了,这样是不是就只需要比较一次了呢。 当然废了这么多话,还没说到HashMap在java7和java8中的区别(坐下,放下你手中的40米大刀),那么,你想下,每次计算到相同的hash值,新的值会代替老的值,那么它是怎么插入的呢(懂得已经懂了,嘿嘿)