前言

大家好啊,我是汤圆,明天给大家带来的是《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的汇合

上面咱们简略看下三者的区别

HashMapTreeMapLinkedHashMap
访问速度适中
元素是否有序无序有序,默认按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差

后记

最初,感激大家的观看,谢谢