大家好啊,我是汤圆,今天给大家带来的是《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接口
HashMapHashMap内部是数组+链表的结构;
因为在添加键值对的时候,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了。
关于自动装箱和拆箱,网上资源很多,这里就不再细说了
TreeMapTreeMap在插入的时候,可以按照键的顺序进行排序
它适合用在排序比较多的场景,性能会比HashMap差一些
LinkedHashMapLinkedHashMap拥有HashMap的大部分优点,且保证了插入的顺序,使得在查询的时候,可以按照插入的顺序依次读取
三者的排序比较下面用代码演示一下,依次插入100个数,看看他们分别是怎么排序的