前言
大家好啊,我是汤圆,明天给大家带来的是《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对应的值,如果没有,则返回nulldefault 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差
后记
最初,感激大家的观看,谢谢