【Java】の基础——HashMap


##哈希表
说道HashMap,不得不提起哈希表(即散列表)这个存储结构。
平时我们在线性表(数组)中存储数据,查找一个数据需要逐个比较。那么有没有什么办法能更快查找到数据呢?
举个例子:

存储 22 41 53 46 29 14 01 这7个数存在下标0-10的数组中

我们可以事先定义一个规则(称为-哈希函数):

H(k) = key%p
说白了就是对数组长度取余数。
H(22)=22%11=0
H(41)=41%11=8
H(53)=53%11=9
H(46)=46%11=2
H(29)=29%11=7
H(14)=14%11=3
H(01)=01%11=1

存入数组结果是:
这里写图片描述
在查找的时候我们只要把key按照规则运算然后去查找就可以了,这就是哈希表。

但是,如果此时再存入 24,H(24)=24%11=2
我们会发现,根据规则查找到的位置2已经被人占用了,这种情况称为:哈希冲突。(本文就不从数据结构层面讨论解决哈希冲突的办法啦)

HashMap

Map

Map
提供了interface Entry<K,V> { },将键映射到值的对象,一个key对应一个value的存储结构。
###HashMap
首先我们看看HashMap的结构:
这里写图片描述

首先,它定义了一个Node:

	Node<K,V>{
		int hash;
		K key;
		V value;
		Node<K,V> next;
	}

可以看出Node是一个链表的结点。

	Node<K,V>[] table;

而存储的主体table,则是Node的数组。

HashMap还有两个重要的值:

  • 加载因子(默认0.75):扩容的标准
  • 容量(初始值16):table的长度

我们可以结合HashMap创建的过程来看:

  • 首先默认创建一个长度为16的数组。
  • 当存入对象时,根据key的hashcode值对HashMap的容量求余数,决定该对象存放在数组中的位置。
    如果该位置已经有对象,则以链表的形式存储(jdk1.8之前用头插法,1.8用尾插法)。
  • 当然,如果table数组已经占满75%(根据加载因子0.75),那么就对哈希表进行扩充,这个过程称为重新散列,将其容量扩大一倍。
  • 此外,在jdk1.8中,如果一个链表节点数大于8,那么将其转化为红黑树进行存储。如果小于6,退化为链表。

FAQ:

1 HashMap时间复杂度
最好:O(1) ;最差O(n) 或者 O(logn) (要看是链表还是红黑树)

2 为什么扩容扩大一倍?
这样尽可能的减少元素位置的移动。
具体分析

HashTable

HashMap是HashTable的轻量级实现,HashMap 不是线程安全
HashTable的方法都加了同步锁,因此是线程安全的。相应的,它的效率也较低。

ConcurrentMap

ConcurrentMap是线程安全的Map。
ConcurrentHashMap的同步机制和HashTable不同,它不是加synchronized关键字,而是基于lock操作的,这样的目的是保证同步的时候,锁住的不是整个对象。
相比较于HashMap,ConcurrentHashMap包含的是Segment数组,Segment继承于ReentrantLock。多线程Put同一个hash值的键值对时,只锁住对应的Segment。
对于value用volatile修饰,保证多线程在Get时取值正确,效率也高。

TreeMap

TreeMap是一个有序的key-value集合,它是通过红黑树实现的。
该映射根据其键的自然顺序(升序)进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。

LinkedHashMap

LinkedHashMap 是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值