Hashmap的与hashtable的区别:

Hashmap:允许key为空;查询速度快(他是非同步的:避免了同步中不必要的判断);不安全的(容易引  发多线程安全问题)

Hashtable:不允许key为空,查询速度慢(他是线程同步的,从而降低了效率,但是保证了安全)

Hashmap已经取代hashtable

你知道hashmap的工作原理吗?

HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap 中获取对象。当我们给put()方法传递键和值时,我们先对键调用 hashCode()方法,返回的hashCode用于 找到bucket位置来储存Entry对象。”HashMap是在 bucket中储存键对象和值对象,作为Map.Entry。

当两个对象的hashcode相同会发生什么?

因为hashcode相同,所以它们的bucket位置相同,‘碰撞’会发生。这时将要插入的keyhashmap中与这个key的hashcode值相同的key通过equals判断:

如果返回true,将视为同一个对象,会将新的value替换掉原来的value;

如果返回false,因为HashMap使 用链表存储对象, 这个Entry(包含有键值对的Map.Entry对象)会存储在链表中。

“如果两个键的hashcode相同,你如何获取值对象?”

当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位置,然后获取值对象。如果有两个值对象储存在同一个bucket,找到bucket位置之后,会调用keys.equals()方法去找到链表中正确的节点, 最终找到要找的值对象

(补充回答)使用不可变的、声明作final的对象,并且采用合适的equals()和 hashCode()方法的话,将会 减少碰撞的发生,提高效率。不可变性使得能够缓存不同键的hashcode,这将提高整个获取对象的速度, 使用 String,Interger这样的wrapper类作为键是非常好的选择。

如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?

默认的负载因子大小为0.75,也就是说,当一个map填满了75%的bucket时候,和其它集合类(如ArrayList 等)一样,将会创建原来HashMap大小的两倍的bucket数组,来重新调整map的大小,并将原来的对象 放入新的bucket数组中。这个过程叫作rehashing,因为它调用hash方法找到新的bucket位置。

你了解重新调整HashMap大小存在什么问题吗?

当多线程的情况下,可能产生条件竞争(race condition)。

当重新调整HashMap大小的时候,确实存在条件竞争,因为如果两个线程都发现HashMap需要重新调整 大小了,它们会同时试着调整大小。在调 整大小的过程中,存储在链表中的元素的次序会反过来,因为 移动到新的bucket位置的时候,HashMap并不会将元素放在链表的尾部,而是放在头部, 这是为了避免 尾部遍历(tail traversing)。如果条件竞争发生了,那么就死循环了。我个人认为在多线程的环境下使用 HashMap 是不合理的

回答过程中的细节问题:

为什么String, Interger这样的wrapper类适合作为键?

String, Interger这样的wrapper类作为HashMap的键是再适合不过了,而且String最为常用。因为String是不可变的,也是final 的,而且已经重写了equals()和hashCode()方法了。其他的wrapper类也有这个特点。不可变性是必要的,因为为了要计算 hashCode(),就要防止键值改变,如果键值在放入时和获取时返回不同的hashcode的话,那么就不能从HashMap中找到你想要的对象。不 可变性还有其他的优点如线程安全。如果你可以仅仅通过将某个field声明成final就能保证hashCode是不变的,那么请这么做吧。因为获取对象 的时候要用到equals()和hashCode()方法,那么键对象正确的重写这两个方法是非常重要的。如果两个不相等的对象返回不同的 hashcode的话,那么碰撞的几率就会小些,这样就能提高HashMap的性能。

我们可以使用自定义的对象作为键吗?

当然,你可能使用任何对象作为键,但是要想得到你想要的结果,他必须满足一定的条件:

(1)重写hashcode方法,在不重写的情况下,hashcode()的返回值根据在Object类中的定义是返回的是根据地址在内存中的位置转换成的int值,也就是任意两个对象的hashcode()都不相同,因此存进hashmap的值就无法取出。例:

(2)作为只要它遵守了equals()和hashCode()方法的定义规则,并且当对象插入到Map中之 后将不会再改变了。如果这个自定义对象时不可变的,那么它已经满足了作为键的条件,因为当它创建之后就已经不能改变了。

我们可以使用CocurrentHashMap来代替Hashtable吗?

他是JDK 1.5引入的并发集合类,对于大型的、要求低延迟的电子商务系统来说非常的有用。

Hashtable和ConcurrentHashMap有什么分别呢?它们都可以用于多线程的环境,但是当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。因为ConcurrentHashMap引入了分割,不论它变得多么大,仅仅需要锁定map的某个部分,而其它的线程不需要等到迭代完成才能访问map。简而言之,在迭代的过程中,ConcurrentHashMap仅仅锁定map的某个部分,而Hashtable则会锁定整个map.ConcurrentHashMap其实采用了并发的思想,当某个锁使用到的时候,仅仅是在这个锁的控制范围内其他的对象不可以访问,在其他的部分,其他的对象仍然可以访问。

HashMap与ConcurrentHashMap的区别

从JDK1.2起,就有了HashMap,HashMap相对于hashtable有很多优点,但是也有他的不足之处。他是线程不安全的,多线程操作时容易导致死锁的发生。

在JDK1.5中,新增了concurrent包,从此Map也有安全的了。

与hashtable实现同步的方式不同,它引入了一个“分段锁”的概念,具体可以理解为把一个大的Map拆分成N个小的Segment(类似HashTable),根据key.hashCode()来决定把key放到哪个Segment中。在ConcurrentHashMap中,就是把Map分成了N个Segment,put和get的时候,都是现根据key.hashCode()算出放到哪个Segment中

详细解析 ConcurrentHashMap

hashMap归纳的更多相关文章

  1. Java集合之HashMap

    1. HashMap概述: HashMap是基于哈希表的Map接口的非同步实现(Hashtable跟HashMap很像,唯一的区别是Hashtalbe中的方法是线程安全的,也就是同步的).此实现提供所 ...

  2. java HashMap那点事

    集合类的整体架构 比较重要的集合类图如下:   有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否 否 HashSet TreeSet 是(用二 ...

  3. HashMap的工作原理深入再深入

    前言 首先再次强调hashcode (==)和equals的真正含义(我记得以前有人会说,equals是判断对象内容,hashcode是判断是否相等之类): equals:是否同一个对象实例.注意,是 ...

  4. hash-2.hashMap

    1.HashMap的数据结构 a.HashMap是一个链表散列的结合体,即,数组和链表的结合体. b.HashMap类中定义了Entry类型的数组,Entry [ ] ,Entry有key value ...

  5. java中HashMap详解

    HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,其中 HashMap 是 Map 接口的常用实现类,HashSet 是 Set 接口的常用实 ...

  6. Java集合---HashMap源码剖析

    一.HashMap概述二.HashMap的数据结构三.HashMap源码分析     1.关键属性     2.构造方法     3.存储数据     4.调整大小 5.数据读取           ...

  7. HashMap原理详解

    HashMap 概述 HashMap 是基于哈希表的 Map 接口的非同步实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.此类不保证映射的顺序,特别是它不保证该顺序恒久不 ...

  8. 转:HashMap深度解析(一)

      HashMap哈希码hashCodeequals 本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/16843543,转载 ...

  9. 深入Java集合学习系列:HashMap的实现原理

    1.    HashMap概述: HashMap是基于哈希表的Map接口的非同步实现.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序恒久不变 ...

随机推荐

  1. spring Mvc + Maven + 拷贝插件 (十一)

    maven-antrun-plugin:可用于在项目编译打包时,把文件指定的文件拷贝到指定的位置,我们打包一般都是打包到 项目 的target 文件下; <groupId>org.apac ...

  2. mysql学习------错误日志和通用查询日志

    一.启动错误日志 1.在不同情况下,错误日志会记录在不同的位置.如果没有在配置文件中指定文件名,则文件名默认为hostname.err 2.在mysql5.6的rpm发布方式中,错误的日志默认的放置在 ...

  3. Apache+jboss群集优化

    故障现象: 俩台服务器jboss做的Apache群集,之前优先访问A,造成大量session都在A上有报警. 调整 调整Apache 配置jboss集群参数,将Node2的worker.node2.l ...

  4. centos下配置nginx支持php

    添加nginx 默认主页index.php vim .../etc/nginx/conf.d/default.conf location / { root   /usr/share/nginx/htm ...

  5. 八、vue使用element-ui组件

    element-ui组件 1.引入element import Vue from 'vue'; import ElementUI from 'element-ui'; import 'element- ...

  6. 在Scrapy项目【内外】使用scrapy shell命令抓取 某网站首页的初步情况

    Windows 10家庭中文版,Python 3.6.3,Scrapy 1.5.0, 时隔一月,再次玩Scrapy项目,希望这次可以玩的更进一步. 本文展示使用在 Scrapy项目内.项目外scrap ...

  7. java 嵌套接口

    接口可以嵌套在其它类或接口中,可以拥有public和"包访问权限"两种可见性 作为一种新添加的方式,接口也可以实现为private 当实现某个接口时,并不需要实现嵌套在其内的任何接 ...

  8. 【PAT】1060 Are They Equal (25)(25 分)

    1060 Are They Equal (25)(25 分) If a machine can save only 3 significant digits, the float numbers 12 ...

  9. Angular快速学习笔记(4) -- Observable与RxJS

    介绍RxJS前,先介绍Observable 可观察对象(Observable) 可观察对象支持在应用中的发布者和订阅者之间传递消息. 可观察对象可以发送多个任意类型的值 -- 字面量.消息.事件. 基 ...

  10. json字符串的标准格式

    现在越来越多的项目和开发插件等默认都会支持和使用json数据格式,作为数据保持.传输的一种方式. 说是其中一种,就标示还有好多其他格式.比如:最多是xml.webservice的标准数据格式. 不过由 ...