集合有两个大接口:Collection 和 Map,本文重点来讲解集合中另一个常用的集合类型 Map。

以下是 Map 的继承关系图:

avatar

Map 简介

Map 常用的实现类如下:

Hashtable:Java 早期提供的一个哈希表实现,它是线程安全的,不支持 null 键和值,因为它的性能不如 ConcurrentHashMap,所以很少被推荐使用。

HashMap:最常用的哈希表实现,如果程序中没有多线程的需求,HashMap 是一个很好的选择,支持 null 键和值,如果在多线程中可用 ConcurrentHashMap 替代。

TreeMap:基于红黑树的一种提供顺序访问的 Map,自身实现了 key 的自然排序,也可以指定 Comparator 来自定义排序。

LinkedHashMap:HashMap 的一个子类,保存了记录的插入顺序,可在遍历时保持与插入一样的顺序。

Map 常用方法

常用方法包括:put、remove、get、size 等,所有方法如下图:

enter image description here

使用示例,请参考以下代码:

Map hashMap = new HashMap();

// 增加元素

hashMap.put("name", "老王");

hashMap.put("age", "30");

hashMap.put("sex", "你猜");

// 删除元素

hashMap.remove("age");

// 查找单个元素

System.out.println(hashMap.get("age"));

// 循环所有的 key

for (Object k : hashMap.keySet()) {

System.out.println(k);

}

// 循环所有的值

for (Object v : hashMap.values()) {

System.out.println(v);

}

以上为 HashMap 的使用示例,其他类的使用也是类似。

HashMap 数据结构

HashMap 底层的数据是数组被成为哈希桶,每个桶存放的是链表,链表中的每个节点,就是 HashMap 中的每个元素。在 JDK 8 当链表长度大于等于 8 时,就会转成红黑树的数据结构,以提升查询和插入的效率。

HashMap 数据结构,如下图:

enter image description here

HashMap 重要方法

1)添加方法:put(Object key, Object value)

执行流程如下:

对 key 进行 hash 操作,计算存储 index;

判断是否有哈希碰撞,如果没碰撞直接放到哈希桶里,如果有碰撞则以链表的形式存储;

判断已有元素的类型,决定是追加树还是追加链表,当链表大于等于 8 时,把链表转换成红黑树;

如果节点已经存在就替换旧值;

判断是否超过阀值,如果超过就要扩容。

源码及说明:

public V put(K key, V value) {

// 对 key 进行 hash()

return putVal(hash(key), key, value, false, true);

}

static final int hash(Object key) {

int h;

// 对 key 进行 hash() 的具体实现

return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,

boolean evict) {

Node[] tab; Node p; int n, i;

// tab为空则创建

if ((tab = table) == null || (n = tab.length) == 0)

n = (tab = resize()).length;

// 计算 index,并对 null 做处理

if ((p = tab[i = (n - 1) & hash]) == null)

tab[i] = newNode(hash, key, value, null);

else {

Node e; K k;

// 节点存在

if (p.hash == hash &&

((k = p.key) == key || (key != null && key.equals(k))))

e = p;

// 该链为树

else if (p instanceof TreeNode)

e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);

// 该链为链表

else {

for (int binCount = 0; ; ++binCount) {

if ((e = p.next) == null) {

p.next = newNode(hash, key, value, null);

if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st

treeifyBin(tab, hash);

break;

}

if (e.hash == hash &&

((k = e.key) == key || (key != null && key.equals(k))))

break;

p = e;

}

}

// 写入

if (e != null) { // existing mapping for key

V oldValue = e.value;

if (!onlyIfAbsent || oldValue == null)

e.value = value;

afterNodeAccess(e);

return oldValue;

}

}

++modCount;

// 超过load factor*current capacity,resize

if (++size > threshold)

resize();

afterNodeInsertion(evict);

return null;

}

put() 执行流程图如下:

enter image description here

java map 面试题_Java 面试系列:集合详解之 Map + 面试题相关推荐

  1. Java集合详解之Map

    一.首先看看集合框架体系图 从图中可以看到,Map接口扩展了Iterator接口,关于Iterator接口详解请移步:Iterator接口详解 二.Map是什么? Map<k,v>使用键值 ...

  2. java代码轻量级锁_Java轻量级锁原理详解(Lightweight Locking)

    转自http://www.cnblogs.com/redcreen/archive/2011/03/29/1998801.html 大家知道,Java的多线程安全是基于Lock机制实现的,而Lock的 ...

  3. java单例设计模式_Java设计模式之单例模式详解

    在Java开发过程中,很多场景下都会碰到或要用到单例模式,在设计模式里也是经常作为指导学习的热门模式之一,相信每位开发同事都用到过.我们总是沿着前辈的足迹去做设定好的思路,往往没去探究为何这么做,所以 ...

  4. java的static类_java中staticclass静态类详解

    一般情况下是不可以用static修饰类的.如果一定要用static修饰类的话,通常static修饰的是匿名内部类. 在一个类中创建另外一个类,叫做成员内部类.这个成员内部类可以静态的(利用static ...

  5. Java 初始化 代码块_Java中初始化块详解及实例代码

    Java中初始化块详解 在Java中,有两种初始化块:静态初始化块和非静态初始化块. 静态初始化块:使用static定义,当类装载到系统时执行一次.若在静态初始化块中想初始化变量,那仅能初始化类变量, ...

  6. java connection 单例_Java设计模式之单例模式详解

    Java设计模式之单例模式详解 什么是设计模式 设计模式是在大量的实践中总结和理论之后优选的代码结构,编程风格,以及解决问题的思考方式.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可 ...

  7. java指数表示法_Java指数计数法详解

    Java指数计数法详解 时间:2017-10-16     来源:华清远见Java培训中心 Java指数计数法并不是一个很难的运算,关键是你要理解应用,很多朋友不理解Java指数计数法,所以也无从运用 ...

  8. java方法怎么写_java方法定义格式详解,java方法怎么写?

    对于java方法你了解多少呢?你知道java方法应该如何写吗?下面要给大家介绍的就是和java方法相关的内容,一起来了解一下这个概念吧. 在学习运算符的时候,都为每个运算符单独的创建一个新的类和mai ...

  9. java解析json数据_java解析JSON数据详解

    JSON是目前最流行的轻量级数据交换语言(没有之一).尽管他是javaScript的一个子集.但由于其是独立与语言的文本格式,它几乎可以被所有编程语言所支持. 以下是对java语言中解析json数据的 ...

最新文章

  1. [BZOJ1131][POI2008]Sta
  2. 网页去重||SimHash(高效的文本相似度去重算法)——适合大批量文档的相似度计算
  3. jq之mousedown
  4. 制药企业核算报表系统整体方案
  5. CentOS 8,凛冬将至
  6. C# 使用Newtonsoft.Json读写Json文件
  7. Blocking waiting for file lock on package cache
  8. 40. Use multiple inheritance judiciously
  9. htlm5实习报告_JSP实习报告
  10. 常见的Ajax写法汇总
  11. 400企业智能服务器,全球领先的企业级服务器、存储、融合系统及解决方案-H3C与HPE...
  12. 【第8章】Java常用核心类
  13. Xftp的下载、安装、使用
  14. php 微信 防刷票,细数那些防止微信刷票的设置
  15. Docker拉取镜像报错error pulling image configuration
  16. selenium定位H5表单验证的提示语
  17. 【Rust日报】 2019-04-27
  18. web(ASP)常用代码
  19. 外贸:圣诞新年祝福语语
  20. 跨越-丢掉你躯体内可怜的想法

热门文章

  1. 马化腾:《王者荣耀》将举办AI电竞赛;美团发布自研无人机,15分钟配送到家;微软将为员工发放1500美元奖金|极客头条...
  2. 华为今年不发布Mate系列新机;一加宣布与OPPO合并:将成为OPPO旗下独立品牌;Gradle 7.1 发布|极客头条...
  3. Rust 升级成微软第一梯队语言;“熊孩子”乱敲键盘攻破 Linux 桌面;500 个值得学习的 AI 开源项目| 开发者周刊...
  4. 百密一疏,防不胜防,细数那些大型数据库建设过程中绕不开的坑
  5. 英伟达斥资 400 亿美元收购 Arm,欲向 Arm 员工发 15 亿美元股票
  6. TIOBE 9 月编程语言:C++ 突起、Java 流行度下降
  7. GitHub 一周热点:听说程序员都是颜控?
  8. 如何使用 SQL Server FILESTREAM 存储非结构化数据?
  9. 你值得拥有的 11 个前端开发利器
  10. 滴滴章文嵩:一个人的 20 年开源热情和国内互联网开源运动