HashMap HashSet ConcurrentHashMap相关知识点小结

1.HashMap的底层实现原理

HashMap通过put()和get()方法存值和取值。

存值时,通过hashcode()方法计算键的hashcode值,然后找到对应的bucket位置来存储键值对,如果两个键值对的键的hashcode值相同,则调用键对象的equals()方法来判断两个键对象是否相同,若相同,新值替换旧值并返回旧值(例:原先(16,21),现put(16,22)则22替换21并返回21),如果两个键对象不同,则使用链表来解决碰撞问题,键值对将会存储在链表的下一个节点中。

取值时,通过键对象的equals方法对比传进来的参数,从而找到正确的键值对,然后返回值对象。

相关面试题:

  • 什么是HashMap,你为什么用到它?
  • HashMap的工作原理是什么?HashMap的get()方法的工作原理?
  • 当两个对象的hashcode相同会发生什么?
  • 如果两个键的hashcode相同,你如何获取值对象?
  • 如果HashMap的大小超过了负载因子定义的容量,怎么办?
  • 在多线程情况下,重新调整HashMap大小会存在什么问题吗?
  • 为什么String,Integer这样的wrapper适合作为键?
  • 我们可以使用自定义的对象作为键吗?

详情链接: HashMap底层实现原理及面试问题

2.HashMap与HashSet区别

HashSet:实现了Set接口,不允许集合中有重复的值,将对象存储在HashSet之前,要先确保对象重写equals()和hashCode()方法,这样才能比较对象的值是否相等,以确保set中没有存储相等的对象。如果没有重写这两个方法,将会使用这个方法的默认实现。

HashMap:实现了Map接口,Map接口对键值进行映射,键不允许重复,Map接口有两个基本实现,HashMap和TreeMap,TreeMap保存了对象的排列次序,而HashMap则不能。HashMap允许键和值为null,HashMap是非synchronized的。

区别

  • HashMap使用键对象来计算hashcode值;HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以需要使用equals()方法比较对象是否相等,若相等则返回false,否则插入。
  • HashMap比较快,因为是使用唯一的键来获取对象,而HashSet通过遍历来获取对象。

3.HashMap与HashTable区别

  • 初始长度:HashMap默认情况下容量是16,如果用户通过构造函数指定了一个数字作为容量,那么Hash会选择大于该数字的第一个2的幂作为容量(3–4,7–8,9–16)。HashTable默认初始化长度为11.

  • 扩容:HashMap:当HashMap中的元素个数超过数组大小loadFactor时,就会进行数组扩容,loadFactor的默认值是0.75,默认情况下,数组大小16,当hashmap中元素个数超过160.75=12的时候,就把数组大小扩展为2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置。HashTable:扩容大小是2倍旧长度+1

  • 线程安全:HashMap是非synchronized,而HashTable是synchronized,HashTable是线程安全的,多个线程可以共享一个HashTable;如果没有正确的同步的话,多个线程是不能共享HashMap的。

  • 速度:由于HashTable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果不需要同步,只需要单一线程,那么使用HashMap性能要好过HashTable.

  • 迭代器:HashMap的迭代器(Iterator)是fail-fast迭代器,而HashTable的enumerator迭代器不是fail-fast的。

  • 其他
    (1)HashMap可以允许存在一个为null的key和任意个为null的value,但是HashTable中的key和value都不允许为null。当HashMap遇到null的key时,它会调用putForNullKey方法来进行处理,对于value没有进行任何处理,只要是对象即可。而当hashtable遇到null时,他会直接抛出NullPointerException异常信息。

    (2)HashTable基于Dictionary类,而HashMap是基于AbstractMap。Dictionary是可以将键映射到相应值得类的抽象符类,而AbstractMap是基于Map接口实现的,它以最大限度地减少实现此接口所需的工作。

HashTable链接:java提高篇(二五)-----HashTable

4.enumerator迭代器和Iterator迭代器

(1)函数接口不同

Enumeration只有2个函数接口。通过Enumeration,我们只能读取集合的数据,而不能对数据进行修改。

Iterator只有3个函数接口。Iterator除了能读取集合的数据之外,也能数据进行删除操作。

(2)Iterator支持fail-fast机制,而Enumeration不支持

Enumeration 是JDK 1.0添加的接口。使用到它的函数包括Vector、Hashtable等类,这些类都是JDK 1.0中加入的,Enumeration存在的目的就是为它们提供遍历接口。Enumeration本身并没有支持同步,而在Vector、Hashtable实现Enumeration时,添加了同步。

而Iterator 是JDK 1.2才添加的接口,它也是为了HashMap、ArrayList等集合提供遍历接口。Iterator是支持fail-fast机制的:当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。

fail-fast:它是Java集合的一种错误检测机制。当多个线程对集合进行结构上的改变的操作时,有可能会产生fail-fast机制。记住是有可能,而不是一定。例如:假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生fail-fast机制。

详情链接:enumerator迭代器和Iterator迭代器浅述

5.Hashtable和ConcurrentHashMap异同点

相同点:Hashtable和ConcurrentHashMap存储的内容为键-值对(key-value),且它们都是线程安全的容器。

不同点

  • Hashtable通过使用synchronized修饰方法的方式来实现多线程同步,因此,Hashtable的同步会锁住整个数组。在高并发的情况下,性能会非常差。
  • ConcurrentHashMap作为高吞吐量的线程安全HashMap实现,它采用了锁分离的技术允许多个修改操作并发进行。
    ConcurrentHashMap采用了更细粒度的锁来提高在并发情况下的效率。ConcurrentHashMap将Hash表默认分为16个桶(每一个桶可以被看作是一个Hashtable),大部分操作都没有用到锁,而对应的put、remove等操作也只需要锁住当前线程需要用到的桶,而不需要锁住整个数据。采用这种设计方式以后,在大并发的情况下, 同时可以有16个线程来访问数据。显然,大大提高了并发性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值