前言

大家好啊,我是汤圆,今天给大家带来的是《Java中的映射Map - 入门篇》,希望对大家有帮助,谢谢

简介

前面介绍了集合List,这里开始简单介绍下映射Map,相关类如下图所示

正文

Map是一种存储键值对的数据集合,键以散列或者树形结构进行存储;

为什么会设计Map接口呢?

假设我们有一个员工类,里面有Id属性和姓名等其他信息,现在我们把所有员工都存到List里,然后要找出Id为001的员工,你会发现,你需要从List中遍历每个对象,然后取出Id进行比较;

你会发现这种查找法效率很低,有点杀鸡用牛刀的感觉;

这时如果有一个集合类,可以以键值对映射的方式的存储员工信息(Id作为键,员工信息作为值),那么就可以只遍历键列表,然后进行比较;

你会发现这种查找法效率提高了很多,因为物尽其用了(比较的是Id,也只是取了Id,没有浪费);

这就是Map接口的作用,可以根据某个键去查找对应的信息,有点类似于数据库的设计。

Map的种类

Map主要有三种类型:HashMap(常用)、TreeMap(树形结构)、LinkedHashMap(前两者的结合)

我们先来看一下Map接口主要的几个方法:

  • V put(K key, V value):往Map中添加键值对,其中key为键,value为值;如果key存在,则覆盖原有的值;如果不存在,则新建键值对。
  • V get(Object key):从Map中查找键key对应的值,如果没有,则返回null
  • default V getOrDefault(Object key, V defaultValue):从Map中查找键key对应的值,如果没有,则返回第二个参数(设置的默认值);这里的修饰符default是用在接口方法中,表示这个方法在接口中已经实现了,子类可以不实现(Java8开始支持)
  • Set<K> keySet():返回Map中Key的集合;之所以返回Set,是因为Map中的key不能有重复,所以用Set最适合了
  • Collection<V> values():返回Map中Values的集合

下面我们简单看下三者的区别

HashMap TreeMap LinkedHashMap
访问速度 适中
元素是否有序 无序 有序,默认按key排序 有序,默认按插入的顺序
适用场景 普通的插入,查询(用的最多) 需要对key进行排序的场景(比如员工按年龄排序等) 需要保证查询和插入顺序一致的场景(类似队列)

接下来我们以HashMap为例,来介绍Map接口

HashMap

HashMap内部是数组+链表的结构;

因为在添加键值对的时候,Key做了hash处理,然后按照hash值进行排列;

  • 如果hash值没有重复,就按照数组的方式依次排列;
  • 如果hash值有重复的,就添加到已有的键值对后面(Java8以后是尾部插入),形成链表结构;

整体结构 如下图所示

这里只是简单介绍,以后再深入了解

下面用代码示范一下

// 键值对集合,键不可以重复
Map<String, Integer> map = new HashMap<>();
// 添加:首先会检查对应的key是否存在,如果不存在,则新建键值对,然后填充;如果存在,则覆盖已有的值
map.put("a", 1); // 这里的1会自动装箱为Intege类型
// 查询
int value1 = map.get("a");
int value2 = map.get("b");
System.out.println(map);

这里有个很有意思的现象,你觉得value2会是多少呢?

答案是多少都不是,因为程序运行到这一行就出错了,报空指针异常

不应该返回null吗?怎么会出错?

这里涉及到拆箱和装箱的问题,上面我们在添加put的时候,int 1自动装箱为Integer;

然后在获取get的时候,对应的也是要进行拆箱的,将Integer转为int;

但是由于获取的value = null,所以就相当于对null进行拆箱,结果就报错了。

解决办法就是严格按照Map的类型信息进行添加和获取;

将上面的代码加以修改,如下所示

// 键值对集合,键不可以重复
Map<String, Integer> map = new HashMap<>();
// 添加:首先会检查对应的key是否存在,如果不存在,则新建键值对,然后填充;如果存在,则覆盖已有的值
map.put("a", 1); // 这里的1会自动装箱为Intege类型
// 查询
Integer value1 = map.get("a");
Integer value2 = map.get("b");
System.out.println(map);

此时value2就等于null了。

关于自动装箱和拆箱,网上资源很多,这里就不再细说了

TreeMap

TreeMap在插入的时候,可以按照键的顺序进行排序

它适合用在排序比较多的场景,性能会比HashMap差一些

LinkedHashMap

LinkedHashMap拥有HashMap的大部分优点,且保证了插入的顺序,使得在查询的时候,可以按照插入的顺序依次读取

三者的排序比较

下面用代码演示一下,依次插入100个数,看看他们分别是怎么排序的

HashMapDemo.java

public class HashMapDemo {
public static void main(String[] args) {
// 键值对集合,键不可以重复
Map<String, Integer> map = new HashMap<>();
// 倒序插入100个数
int i =100;
while (i-->0){
map.put(""+i, i);
}
// 查询
for (String str :
map.keySet()) {
// 这里会乱序输出
System.out.println(str);
}
}
}

输出如下所示:很乱

TreeMapDemo.java


public class MapDemo {
public static void main(String[] args) { // TreeMap
Map<String, Integer> map1 = new TreeMap<>();
// 连续倒序插入100个数
int k =100;
while (k-->0){
map1.put(""+k, k);
}
// 查询
for (String str :
map1.keySet()) {
// 这里会正序输出
System.out.println(str);
}
}
}

输出如下所示:

细心的你们,应该会发现上面的输出有点别致

那是因为这里的键key(0~99)其实不是整型,而是字符串类型,所以排序按照字符串的升序来排,才会出现如图所示的结果

(建议实际场景不要这样搞,容易出事,字符串尽量不要用纯数字,而是要跟字母做拼接;)

正确的做法是key=“a”+i,这种方式

LinkedHashMapDemo.java


public class MapDemo {
public static void main(String[] args) {
// LinkedHashMap
Map<String, Integer> map2 = new LinkedHashMap<>();
// 倒序插入100个数
int j =100;
while (j-->0){
map2.put("a"+j, j);
}
for (String str :
map2.keySet()) {
// 这里按照插入的顺序依次输出
System.out.println(map2.get(str));
}
}
}

输出如下所示:

总结

Map一般用到的有HashMap,TreeMap,LinkedHashMap,当然还有并发相关的,这里入门级别的先不涉及(比如ConcurrentHashMap)

  • HashMap的插入和访问都很快,但是内部是无序排列

  • TreeMap的插入和访问都很慢,但是内部是有序排列,默认按key升序排列

  • LinkedHashMap拥有HashMap的大部分优点,而且还可以按照元素插入的顺序来访问元素,但是性能会比HashMap差

后记

最后,感谢大家的观看,谢谢

Java中的映射Map - 入门篇的更多相关文章

  1. Java中的集合Set - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的集合Set - 入门篇>,希望对大家有帮助,谢谢 简介 前面介绍了集合List,映射Map,最后再简单介绍下集合Set,相关类如下 ...

  2. Java中的IO流 - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的IO流-入门篇>,希望对大家有帮助,谢谢 由于Java的IO类有很多,这就导致我刚开始学的时候,感觉很乱,每次用到都是上网搜,结果 ...

  3. Java中的集合List - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的集合List - 入门篇>,希望对大家有帮助,谢谢 简介 说实话,Java中的集合有很多种,但是这里作为入门级别,先简单介绍第一种 ...

  4. Java中如何遍历Map对象的4种方法

    在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都实现了Map接口,以下方法适用于任何map实现(HashMap, TreeMap, LinkedHa ...

  5. 转!! Java中如何遍历Map对象的4种方法

    在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...

  6. 【转】Java中如何遍历Map对

    在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...

  7. 【转】Java中如何遍历Map对象的4种方法

    原文网址:http://blog.csdn.net/tjcyjd/article/details/11111401 在Java中如何遍历Map对象 How to Iterate Over a Map ...

  8. (转)在Java中如何遍历Map对象

    在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...

  9. (转载)Java中如何遍历Map对象的4种方法

    在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...

随机推荐

  1. LeetCode 最大收益的分配工作

    LeetCode 最大收益的分配工作 工作安排 现在有n位工程师和6项工作(编号为0至5),现在给出每个人能够胜任的工作序号表(用一个字符串表示,比如:045,表示某位工程师能够胜任0号,4号,5号工 ...

  2. how to design a search component in react

    how to design a search component in react react 如何使用 React 设计并实现一个搜索组件 实时刷新 节流防抖 扩展性,封装,高内聚,低耦合 响应式 ...

  3. 你真的懂 MP4 格式吗?

    MP4 文件格式又被称为 MPEG-4 Part 14,出自 MPEG-4 标准第 14 部分 .它是一种多媒体格式容器,广泛用于包装视频和音频数据流.海报.字幕和元数据等.(顺便一提,目前流行的视频 ...

  4. Python学习相关链接

    感觉挺全的: http://www.cnblogs.com/xinshiye/p/9015187.html 也挺全的:http://www.cnblogs.com/toutou/category/72 ...

  5. 微信小程序:数组拼接

    一开始用concat进行拼接,总是不行,代码如下: handleItemChange(e){ console.log(e) var itemList = e.detail.value itemList ...

  6. 换人!golang面试官:连怎么避免内存逃逸都不知道?

    问题 怎么避免内存逃逸? 怎么答 在runtime/stubs.go:133有个函数叫noescape.noescape可以在逃逸分析中隐藏一个指针.让这个指针在逃逸分析中不会被检测为逃逸. // n ...

  7. docker08容器监控工具-WeaveScope

    容器监控工具WeaveScope 一 背景 在生成环境中k8s应用部署众多,需要一款可视化工具方便日常获知集群的实时状态,并为故障排查提供及时和准确的数据支持. weavescope支持docker和 ...

  8. TorchVision 预训练模型进行推断

    torchvision.models 里包含了许多模型,用于解决不同的视觉任务:图像分类.语义分割.物体检测.实例分割.人体关键点检测和视频分类. 本文将介绍 torchvision 中模型的入门使用 ...

  9. iOS中web与Js的交互

    问题 感觉到uni-app框架有pit,公司强推该框架的小哥识趣的闭嘴,考虑到全盘替换周期跟成本挺大,基于uni-app能打包成H5,采用webview+js的原生方式集成 基本结构:原生壳 + we ...

  10. 基于element-ui封装一个Table模板组件

    大家在做后台管理系统的时候,写的最多的可能就是表格页面了,一般分三部分:搜索功能区.表格内容区和分页器区.一般这些功能都是使用第三方组件库实现,比如说element-ui,或者vuetify.这两个组 ...