Map集合

Map集合

1.简介

映射表(也称关联数组)的基本思想是它维护的是键-值(对)关联,因此你可以使用键来查找值。标准的Java类库中包含了Map的几种基本实现,包括:HashMap、TreeMap、LinkedHashMap,WeakHashMap,ConcurrentHashMap。他们都有同样的基本接口Map,但是行为特性各不相同。这主要表现在效率键值对的保存呈现次序对象的生命周期映射表如何在多线程程序中工作和判定“键”等价的出来方面。

2.映射表的性能

性能是映射表的一个重要问题,当在get()中使用线性搜索时,执行速度会相当地慢。而这正是HashMap提高速度的地方。HashMap使用了特殊的值,称作散列码,来取代对键的缓慢搜索。散列码是相对唯一的、用以代表对象的int值,它是通过将该对象的某些信息进行转换而成的散列码是通过散列函数hashCode()计算出来的一个整数值。hashCode()是根类的Object方法,因此所有的Java对象都能产生散列码

HashMap就是使用对象的hashCode()进行快速查询的,此方法能够显著提高性能。 散列是映射存储元素时最常用的方式。

2.1 散列码

Object的hashCode()方法用来生成散列码,它默认是使用对象的地址计算散列码。如果只覆盖hashCode方法,并不能保证能正常运行。除非你同时覆盖equals方法,它也是Object的一部分。HashMap使用equals()判断当前的键是否与表中存在的键相同默认的Object.equals()只是比较对象的地址如果需要使用自己的类作为HashMap的键,必须同时重载hashCode()和equals()

hashCode并不需要总是返回唯一的标识码,但是equals()方法必须严格地判断两个对象是否相同

散列的价值在于速度:散列使得查询得以快速进行。由于瓶颈位于键的查询速度,因此解决方案之一是保持键的排序状态,然后是使用Collections.binarySearch()进行查询。散列则更进一步,它将键保存在某处,以便能快速找到。存储一组元素最快的数据结构是数组,所以使用它来表示键相关的信息。但数组不保存键本身,而是通过键对象生成一个数字,将其作为数组的下标,这个数字就是散列码。可以通过hashCode方法计算该散列码。

为解决数组容量被固定的问题,不同的键可以产生相同的下标,也就是说,可能会有冲突。解决散列冲突的方法有链地址法、开放地址法

查询的过程是首先利用hashCode()计算散列码,然后使用散列码查询数组。但是通常是存在冲突的,冲突由链地址法处理:数组并不直接保存值,而是保存值的list。然后,对list中的值使用equals()方法进行线性查找。

设计hashCode()时最重要的因素就是:无论何时,对同一个对象调用hashCode()都应该生成同样的值。要想使hashCode实用,它必须速度快,并且必须有意义。它必须基于对象的内容生成散列码。散列码不必是独一无二的,但是通过hashCode和equals,必须能够完全确定对象的身份

2.2 性能因子

我们可以通过手工调整HashMap来提高性能。

容量:表中的桶位数capacity;

初始容量:表在创建时所拥有的桶位数initialCapacity。

尺寸:表中当前存储的项数size。

负载因子:尺寸/容量。空表的负载因子是0,而半满载表的负载因子是0.5。负载轻的表产生冲突的可能性小,因此对插入和查找都是理想的。

HashMap和HashSet都允许指定负载因子的构造器,表示当负载情况达到该负载因子的水平时,容器将自动增加其容量(桶位数),实现方式是使容量大致加倍,并重新将现有对象分布到新的桶位集中。(再散列)

HashMap使用的默认负载因子是0.75,这个因子在时间和空间之间达到了平衡。更高的负载因子可以降低所需要的空间,但是会增加查找的代价。如果知道在HashMap中存储多少项,那么创建一个具有恰当大小的初始容量将可以避免自动再散列的开销。

3.Map集合的一些实现

3.1.Map
3.2.AbstractMap
3.3 HashMap
3.4 LinkedHashMap
3.5 TreeMap
3.6 SortedMap

4.对Map的选择

所有Map实现的插入操作都会随着Map尺寸的变大而明显变慢,但是,查找的代价通常要比插入的要小得多,这是个好消息,因为我们执行查找元素的操作要比执行插入元素的操作多很多。

TreeMap通常要比HashMap要慢,与使用TreeSet一样,TreeMap是一种创建有序列表的方式。当使用Map时,你的第一选择应该是HashMap,只有在你要求Map始终保持有序,才需要使用TreeMap。

LinkedHashMap在插入时比HashMap慢一点,因为它维护散列数据结构的同时还要维护双链表。正是由于这个列表,使得其迭代速度更快。

Map容器的选择说明
HashMap(默认的选择)Map基于散列表的实现。在插入和查询“键值对”的开销是固定的。可以通过构造器设置容量和负载因子,以调整容器的性能。
LinkedHashMap类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入的次序,或者是最近最少使用LRU的次序,只比HashMap慢一点,而在迭代访问时反而更快,因为它使用双向链表维护内部次序。
TreeMap基于红黑树的实现。查看“键”或者“键值对”时,他们会被排序(次序由Comparator或者Comparable决定)。TreeMap的特点在于,所得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。
WeakHashMap弱键映射,允许释放映射所指的对象;这是解决某类特殊问题而设计的。如果映射之外没有引用指向某个“键”,则此“键”可以被垃圾收集器回收。
ConcurrentHashMap一种线程安全的Map,它不涉及同步加锁。

5.Map集合的框架图

Map集合的框架图

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值