Map

1、map

   Java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HashMap、Hashtable、LinkedHashMap和TreeMap

 hashMap:

 HashMap中capacity、loadFactor、threshold、size等概念的解释

1)size表示HashMap中存放KV的数量(为链表和树中的KV的总和)。

 

2)capacity译为容量。capacity就是指HashMap中桶的数量。默认值为16。

扩容时会扩容到之前的两倍

e010908f1df46ccdabbc3f8929a54f857d1.jpg

 

3)loadFactor译为装载因子。装载因子用来衡量HashMap满的程度。loadFactor的默认值为0.75f。计算HashMap的实时装载因子的方法为:size/capacity,而不是占用桶的数量去除以capacity。

装载因子的作用:当创建 HashMap 时,有一个默认的负载因子(load factor),其默认值为 0.75,这是时间和空间成本上一种折衷:增大负载因子可以减少 Hash 表(就是那个 Entry 数组)所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的的操作(HashMap 的 get() 与 put() 方法都要用到查询);减小负载因子会提高数据查询的性能,但会增加 Hash 表所占用的内存空间。

747aa0cdd828919366c86c83e4d27f476b6.jpg

4)threshold表示当HashMap的size大于threshold时会执行resize操作。 
threshold=capacity*loadFactor

5)hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的;

6)hash中桶的概念

哈希表中同一个位置可能存有多个元素,以应对哈希冲突问题。这样,哈希表中的每个位置表示一个哈希桶。

7)hashMap存取的特点

HashMap通过键的hashCode来快速的存取元素。

当不同的对象发生碰撞时,HashMap通过单链表来解决,将新元素加入链表表头,通过next指向原有的元素。单链表在Java中的实现就是对象的引用(复合)。

 

8)为什么Hash冲突会造成HashMAp的查询效率低下?

HashMap里面没有出现hash冲突时,没有形成单链表时,hashmap查找元素很快,get()方法能够直接定位到元素,但是出现单链表后,单个bucket 里存储的不是一个 Entry,而是一个 Entry 链,系统只能必须按顺序遍历每个 Entry,直到找到想搜索的 Entry 为止——如果恰好要搜索的 Entry 位于该 Entry 链的最末端(该 Entry 是最早放入该 bucket 中),那系统必须循环到最后才能找到该元素。

9)为什么要用数组加链表实现存储?

数组:存储区间连续,占用内存严重,寻址容易,插入删除困难

链表:存储区间离散,占用内存比较宽松,寻址困难,插入删除容易

10)put的原理

我们用table[index]表示已经找到的元素需要存储的位置。先判断该位置上有没有元素(这个元素是HashMap内部定义的一个类Entity, 基本结构它包含三个类,key,value和指向下一个Entity的next),没有的话就创建一个Entity<K,V>对象,在 table[index]位置上插入,这样插入结束;如果有的话,通过链表的遍历方式去逐个遍历,看看有没有已经存在的key,有的话用新的value替 换老的value;如果没有,则在table[index]插入该Entity,把原来在table[index]位置上的Entity赋值给新的 Entity的next,这样插入结束。

10)HashMap和HashTable对比?

   hashMap可以接受null值但是HashTable不可以

   HAshMap是线程不安全的但是HashTable是线程安全的

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

  hashMap中去掉了Contions方法

HashTable比HashMAp老旧,HAshTable继承自Dictionary类,Dictionary类现在已经过时的一个类

11)LinkedHashMap

LinkedHashMap是HashMap的一个子类,能保存记录的插入顺序,在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。

12)treeMap

TeeMap能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。

一般情况下,我们用的最多的是HashMap,在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。如果需要输出的顺序和输入的相同,那么用LinkedHashMap 可以实现,它还可以按读取顺序来排列.

TreeMap:基于红黑二叉树的NavigableMap的实现,线程非安全,不允许null,key不可以重复,value允许重复,存入TreeMap的元素应当实现Comparable接口或者实现Comparator接口,会按照排序后的顺序迭代元素,

2、对比currentHashMap

currentHashMap是JDK1.5的并发包下提供的一个线程安全的Map但是相对于HashTable来说效率要高,该类并没有直接实现Map接口而是实现ConCurrentMap接口

ConCurrentMap接口继承map接口

currentHashMap使用分段锁的概念,它只会锁操作的那一段数据而不是整个Map都上锁。

ConcurrentHashMap有很好的扩展性,在多线程环境下性能方面比做了同步的HashMap要好,做了同步的HashMap和HashTable在并发效率上区别不大,但是在单线程下HashMap的效率高于ConcurrentHashMap

concurrentHashMap的原理:

一个ConcurrentHashMap由多个segment组成,每一个segment都包含了一个HashEntry数组的hashtable, 每一个segment包含了对自己的hashtable的操作,比如get,put,replace等操作,这些操作发生的时候,对自己的hashtable进行锁定。由于每一个segment写操作只锁定自己的hashtable,所以可能存在多个线程同时写的情况,性能无疑好于只有一个hashtable锁定的情况。

Segment继承了ReentrantLock,所以它就是一种可重入锁(ReentrantLock)。在ConcurrentHashMap,一个Segment就是一个子哈希表,Segment里维护了一个HashEntry数组,并发环境下,对于不同Segment的数据进行操作是不用考虑锁竞争的。(就按默认的ConcurrentLeve为16来讲,理论上就允许16个线程并发执行)

转载于:https://my.oschina.net/demons99/blog/1921232

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值