Java Map类

Map 提供了一个更通用的元素存储方法。Map 集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值。从概念上而言,可以将 List 看作是具有数值键的 Map。

构造函数定义

public interface Map<K,V> { }

方法

abstract void                 clear()
abstract boolean              containsKey(Object key)
abstract boolean              containsValue(Object value)
abstract Set<Entry<K, V>>     entrySet()
abstract boolean              equals(Object object)
abstract V                    get(Object key)
abstract int                  hashCode()
abstract boolean              isEmpty()
abstract Set<K>               keySet()
abstract V                    put(K key, V value)
abstract void                 putAll(Map<? extends K, ? extends V> map)
abstract V                    remove(Object key)
abstract int                  size()
abstract Collection<V>        values()
  1. Map提供接口分别用于返回 键集、值集或键-值映射关系集。entrySet()用于返回键-值集的Set集合;keySet()用于返回键集的Set集合;values()用户返回值集的Collection集合,因为Map中不能包含重复的键;每个键最多只能映射到一个值。所以,键-值集、键集都是Set,值集时Collection。
  2. Map提供了“键-值对”、“根据键获取值”、“删除键”、“获取容量大小”等方法。

架构

Map架构

如上图:
(01) Map 是映射接口,Map中存储的内容是键值对(key-value)。
(02) AbstractMap 是继承于Map的抽象类,它实现了Map中的大部分API。其它Map的实现类可以通过继承AbstractMap来减少重复编码。
(03) SortedMap 是继承于Map的接口。SortedMap中的内容是排序的键值对,排序的方法是通过比较器(Comparator)。
(04) NavigableMap 是继承于SortedMap的接口。相比于SortedMap,NavigableMap有一系列的导航方法;如"获取大于/等于某对象的键值对"、“获取小于/等于某对象的键值对”等等。
(05) TreeMap 继承于AbstractMap,且实现了NavigableMap接口;因此,TreeMap中的内容是“有序的键值对”!
(06) HashMap 继承于AbstractMap,但没实现NavigableMap接口;因此,HashMap的内容是“键值对,但不保证次序”!
(07) Hashtable 虽然不是继承于AbstractMap,但它继承于Dictionary(Dictionary也是键值对的接口),而且也实现Map接口;因此,Hashtable的内容也是“键值对,也不保证次序”。但和HashMap相比,Hashtable是线程安全的,而且它支持通过Enumeration去遍历。
(08) WeakHashMap 继承于AbstractMap。它和HashMap的键类型不同,WeakHashMap的键是“弱键”。

优化

调整 Map 实现的大小

在哈希术语中,内部数组中的每个位置称作“存储桶”(bucket),而可用的存储桶数(即内部数组的大小)称作容量 (capacity)。为使 Map 对象有效地处理任意数目的项,Map 实现可以调整自身的大小。但调整大小的开销很大。调整大小需要将所有元素重新插入到新数组中,这是因为不同的数组大小意味着对象现在映射到不同的索引值。先前冲突的键可能不再冲突,而先前不冲突的其他键现在可能冲突。这显然表明,如果将 Map 调整得足够大,则可以减少甚至不再需要重新调整大小,这很有可能显著提高速度。

使用负载因子

为了确认何时需要调整Map容器,Map使用了一个额外的参数并且粗略计算存储容器的密度。在Map调整大小之前,使用”负载因子”来指示Map将会承担的“负载量”,也就是它的负载程度,当容器中元素的数量达到了这个“负载量”,则Map将会进行扩容操作。负载因子、容量、Map大小之间的关系如下:负载因子 * 容量 > map大小 ----->调整Map大小。
例如:如果负载因子大小为0.75(HashMap的默认值),默认容量为11,则 11 * 0.75 = 8.25 = 8,所以当我们容器中插入第八个元素的时候,Map就会调整大小。
负载因子本身就是在控件和时间之间的折衷。当我使用较小的负载因子时,虽然降低了冲突的可能性,使得单个链表的长度减小了,加快了访问和更新的速度,但是它占用了更多的控件,使得数组中的大部分控件没有得到利用,元素分布比较稀疏,同时由于Map频繁的调整大小,可能会降低性能。但是如果负载因子过大,会使得元素分布比较紧凑,导致产生冲突的可能性加大,从而访问、更新速度较慢。所以我们一般推荐不更改负载因子的值,采用默认值0.75.

Map哈希映射技术

几乎所有通用Map都使用哈希映射技术。对于我们程序员来说我们必须要对其有所了解。
哈希映射技术是一种就元素映射到数组的非常简单的技术。由于哈希映射采用的是数组结果,那么必然存在一中用于确定任意键访问数组的索引机制,该机制能够提供一个小于数组大小的整数,我们将该机制称之为哈希函数。在Java中我们不必为寻找这样的整数而大伤脑筋,因为每个对象都必定存在一个返回整数值的hashCode方法,而我们需要做的就是将其转换为整数,然后再将该值除以数组大小取余即可。如下:

int hashValue = Maths.abs(obj.hashCode()) % size;
下图是哈希映射的基本原理图:

Map哈希映射技术

在该图中1-4步骤是找到该元素在数组中位置,5-8步骤是将该元素插入数组中。在插入的过程中会遇到一点点小挫折。在众多肯能存在多个元素他们的hash值是一样的,这样就会得到相同的索引位置,也就说多个元素会映射到相同的位置,这个过程我们称之为“冲突”。解决冲突的办法就是在索引位置处插入一个链接列表,并简单地将元素添加到此链接列表。当然也不是简单的插入,在HashMap中的处理过程如下:获取索引位置的链表,如果该链表为null,则将该元素直接插入,否则通过比较是否存在与该key相同的key,若存在则覆盖原来key的value并返回旧值,否则将该元素保存在链头(最先保存的元素放在链尾)。

例子

public class MapDemo
{  public static void main(String[] args)  {  Map<String,Integer> m = new HashMap<String,Integer>();  m.put("zhangsan", 19);  m.put("lisi", 49);m.put("wangwu", 19);  m.put("lisi",20);  m.put("hanmeimei", null);         System.out.println(m);  System.out.println(m.remove("wangwu"));  m.clear();  System.out.println(m);        }
}

总结

  1. Map 是一个键值对(key-value)映射接口。Map映射中不能包含重复的键;每个键最多只能映射到一个值。
  2. Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。
  3. Map 映射顺序。有些实现类,可以明确保证其顺序,如 TreeMap;另一些映射实现则不保证顺序,如 HashMap 类。
  4. Map 的实现类应该提供2个“标准的”构造方法:第一个,void(无参数)构造方法,用于创建空映射;第二个,带有单个 Map 类型参数的构造方法,用于创建一个与其参数具有相同键-值映射关系的新映射。实际上,后一个构造方法允许用户复制任意映射,生成所需类的一个等价映射。尽管无法强制执行此建议(因为接口不能包含构造方法),但是 JDK 中所有通用的映射实现都遵从它。

【Java】Map类相关推荐

  1. java map类说_在Java中,关于HashMap类的描述,以下说法错误的是(   )。

    [单选题]所谓覆盖,也称为重写,是指子类中定义了一个与父类某一方法具有相同型构的方法,这里所说的相同型构所指的不是(). [填空题(主观)]半导体二极管实质上是由 [填空(1)] 构成,其主要特性是 ...

  2. java map常用类及其方法_Day50.Map类常用的方法 -Java常用类、集合#、IO

    Day50.Map类常用的方法 -Java常用类.集合#.IO Day50.Map类常用的方法 -Java常用类.集合#.IO Map类常用的方法 . 总结: 常用方法 添加: put(Object ...

  3. Java工具类——通过配置XML验证Map

    Java工具类--通过配置XML验证Map 背景 在JavaWeb项目中,接收前端过来的参数时通常是使用我们的实体类进行接收的.但是呢,我们不能去决定已经搭建好的框架是怎么样的,在我接触的框架中有一种 ...

  4. 【java基础知识】集合类(含Collection类和Map类)

    集合类 Collection<> 常用方法 Collection<String> c = new ArrayList<String>(); c.add(" ...

  5. Java基础之Map类

    Map类 Map 键(key)值(value)对形式 interface Map<K, V> ​ class HashMap<K, V>哈希表结构 ​ class Tree M ...

  6. 干货:排名前 16 的 Java 工具类!

    2019独角兽企业重金招聘Python工程师标准>>> 干货:排名前 16 的 Java 工具类!   在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最 ...

  7. 排名前 16 的 Java 工具类

    转载来自微信公众号:Java 技术栈.如有侵权,请联系作者删除!! 在 Java 中,工具类定义了一组公共方法,这篇文章将介绍 Java 中使用最频繁及最通用的 Java 工具类.以下工具类.方法按使 ...

  8. java map 教程_Java Map接口

    Java Map接口 在本教程中,我们将学习Java Map接口及其方法. Java collections框架的Map接口提供了Map数据结构的功能. 它实现了Collection接口. map的工 ...

  9. java map 内存_java 使用对象和Map保存字符串占用存储空间对比

    对整体堆大小的影响 创建对象情况 已使用的堆大小 没有使用任何对象 95,805,912 个字节 使用map10000000个相同字符串 1,017,388,888 个字节 创建10000000个空对 ...

最新文章

  1. ETC公布2018线路图,试图追赶ETH
  2. vmboxcentos安装重启又要安装_Windows 10八月更新再遇尴尬:安装失败 或安装后随机重启...
  3. linux socketCAN通信,linux can 总线socket接口测试使用
  4. 根据用户id查询菜单列表(菜单权限问题)
  5. android 代码设置dialog 全屏,Android里把Dialog设置为全屏的方法
  6. Linux——Ubuntu安装Fcitx以及Fcitx输入中文不显示候选词框的解决办法
  7. python爬虫今日头条街拍美图开发背景_【Python3网络爬虫开发实战】6.4-分析Ajax爬取今日头条街拍美图...
  8. spring多数据源分布式事务的分析与解决方案
  9. @class与#import
  10. 美团NLP实习生招聘
  11. PAT 乙级 Java 合集
  12. 卡巴斯基实验室解析勒索软件的发展与攻防
  13. java 连接PLC 问题总结 Windows machine for DCOM access, so as to avoid such exceptions.  [0x00000005]
  14. Xilinx 黑金ZYNQ开发板AX7020,利用VIVADO进行FPGA程序烧录
  15. 如何向oracle中导入数据,Oracle导入导出数据库的语法_Oracle_Oracle语法_Oracle数据库_课课家...
  16. 2021年国际及中国钢材价格走势、价格变化因素及后期钢材价格走势分析[图]
  17. word2003下的神秘咒语——灵活的棕色狐狸跳过懒狗
  18. linux下使用PulseAudio获取扬声器的音量和是否静音(C++)
  19. matlab画图环形颜色渐变,Core Animation实战之环形颜色渐变进度条
  20. 最好的在线SQL优化平台 - PawSQL Cloud来了

热门文章

  1. Anaconda安装之后Spyder闪退解决办法
  2. 云服务器和vps主机有什么 区别,到底哪个更好?
  3. 文本分类实战----数据处理篇----embeddings与vocab中词汇不相覆盖问题的处理办法
  4. 语雀转换发布CSDN和语雀导出图片图片无法识别处理(针对typora)
  5. Springboot:拦截器和过滤器
  6. 如何用python请求接口
  7. web手动进行Form表单提交
  8. 【模型部署】NNI:剪枝和量化
  9. [JSTL]标签的使用
  10. APP开发选择什么框架好? 请看这里!