Java之Map

在Java 中最常用的集合类是 List 和 Map,出自于 java.util 中

List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构建、存储和操作任何类型对象元素列表。List 适用于按数值索引访问元素的情形。(后续会出《Java之List》)

Map 提供了一个更通用的元素存储方法。Map 集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值。

构建

Map 定义了几个用于插入和删除元素的变换方法,如下图

Map数据元素操作方法

Map类可分为三种类型

1. 通用Map,用于在应用程序中管理映射,通常在 java.util 程序包中实现

HashMap、Hashtable、Properties、LinkedHashMap、IdentityHashMap、TreeMap、WeakHashMap、ConcurrentHashMap

2. 专用Map,通常我们不必亲自创建此类Map,而是通过某些其他类对其进行访问

java.util.jar.Attributes、javax.print.attribute.standard.PrinterStateReasons、java.security.Provider、java.awt.RenderingHints、javax.swing.UIDefaults

3. 一个用于帮助我们实现自己的Map类的抽象类

AbstractMap

重点说明一下Map类的 HashMap,TreeMap,HashTable,LinkedHashMap。如下

HashMap:

在Java中,保存数据有两种比较简单的数据结构:数组和链表。数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。HashMap就是将数组和链表组合在一起,发挥了两者的优势,我们可以将其理解为链表的数组。

HashMap是最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null(多条会覆盖);允许多条记录的值为 Null。非同步的。

在HashMap中,有两个比较容易混淆的关键字段:size和capacity ,这其中capacity就是Map的容量,而size我们称之为Map中的元素个数。

在日常开发中,我们经常会像如下方式以下创建一个HashMap

Map map = new HashMap();

上面的代码中,我们并没有给HashMap指定容量,那么,这时候一个新创建的HashMap的默认容量是多少呢?

通过代码得出 (如 HashMap默认容量代码图),当我们创建一个HashMap,如果没有指定容量,那么它的默认容量是16。这个容量16是从何而来呢?要想搞清楚这个问题,就要了解 哈希,对应HashMap的hash方法 (如 HashMap 哈希过程图)。

在JDK 8中,默认容量的定义为:static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 ,其故意把16写成1<<4,就是提醒开发者,这个地方要是2的幂。

那么 HashMap是如何保证其容量一定可以是2^n 的呢?

当我们通过HashMap(int initialCapacity)设置初始容量的时候,HashMap并不一定会直接采用我们传入的数值,而是经过计算,得到一个新值,目的是提高hash的效率。如 (1->1、3->4、7->8、9->16)

HashMap有扩容机制,就是当达到扩容条件时会进行扩容。HashMap的扩容条件就是当HashMap中的元素个数(size)超过临界值(threshold)时就会自动扩容。

在HashMap中,threshold = loadFactor * capacity。

loadFactor是装载因子,表示HashMap满的程度,默认值为0.75f,设置成0.75有一个好处,那就是0.75正好是3/4,而capacity又是2的幂。所以,两个数的乘积都是整数。对于一个默认的HashMap来说,默认情况下,当其size大于12(16*0.75)时就会触发扩容。 

当HashMap中的元素个数(size)超过临界值(threshold)时就会自动扩容,扩容成原容量的2倍,即从16扩容到32、64、128 ...

HashMap默认容量代码图
HashMap 哈希过程图

TreeMap:

能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。

 Hashtable:

与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。

LinkedHashMap:

它保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。

常用API

clear():从 Map 中删除所有映射

remove(Object key):从 Map 中删除键和关联的值

put(Object key, Object value):将指定值与指定键相关联

putAll(Map t):将指定 Map 中的所有映射复制到此 map

entrySet():返回 Map 中所包含映射的 Set 视图。Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素

keySet():返回 Map 中所包含键的 Set 视图。删除 Set 中的元素还将删除 Map 中相应的映射(键和值)

values():返回 map 中所包含值的 Collection 视图。删除 Collection 中的元素还将删除 Map 中相应的映射(键和值)

get(Object key):回与指定键关联的值

containsKey(Object key):如果 Map 包含指定键的映射,则返回 true

containsValue(Object value):如果此 Map 将一个或多个键映射到指定值,则返回 true

isEmpty():如果 Map 不包含键-值映射,则返回 true

size():返回 Map 中的键-值映射的数目


持续更新....

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Map Map集合介绍   Map(也称为字典、关联数组)是用于保存具有映射关系的数据,保存两组值,key和val...
    Hughman阅读 2,773评论 0 1
  • 一、前言 Java集合主要分为三种类型:Set(集)、List(列表)和Map(映射)。 先简单说下集合和数组的区...
    小怪聊职场阅读 11,538评论 4 54
  • Map接口Map内存储的是键/值对这样以成对的对象组(可以把一组对象当成一个元素),通过“键”对象来查询“值”对象...
    涎涎阅读 7,799评论 0 1
  • 1Map Map 定义了键值存储的数据操作的接口, 主要用于键值的存储,使用键可以得到值,并且不允许重复的键,值可...
    不高山阅读 3,388评论 0 0
  • TreeMap TreeMap基于红黑树(Red-Black tree)实现。该映射根据其键的自然顺序进行排序,或...
    01010100阅读 1,131评论 0 0