最近在刷某网站的算法题时,遇到某些问题,想破天际也不知道如何实现,查看解析,官方解析和高亮解析都提到了java中的一种数据类型——HashMap,HashMap是Java三大集合中的一种(另外两种为List和Set)。之前学习java语言时,只简单接触过HashMap,平时使用较多的是LIst集合框架,于是趁着这个机会,再次学习了HashMap。
- 为什么要用HashMap 最直接的答案就是提升效率,降低复杂度。举个最简单的例子,要比较两个数组中的元素是否是一样的问题,如 list_a = [11, 22, 33, 44, 55] list_b = [22, 11, 55, 44, 33] is list_a equals list_b? 我们当然能直接得出答案,两个数组中的元素是一样的,都存放着11,22,33,44,55。我们用最简单暴力的方式为:
for(int i = 0; i < list_a.length; i++){
for(int j = 0; j < list_b.length; j++) {
…
}
}
我们可以很清晰得看到,最暴力的方式去比较,时间复杂度最差为O(n2)。这时候,如果采用HashMap,则可以将时间复杂度减低为O(n)。- HashMap的简单理解
顾名思义,HashMap是Hash和Map的结合,;Map说白了就是键值对(key-value)。熟悉mongo的同学或许知道这类非关系型数据库基本就是key-value结构,在python中也存在map的数据结构。所以HashMap实质上就是将key映射到一个唯一的哈希值上并存储下来(映射规则属于哈希值的底层原理,不是本文的重点,在此不细述)。于是在查询或者遍历的时候,我们并不关心我们自己存储数据的先后顺序,只需要根据key的值经过映射,找到对应的哈希值,然后拿到对应的value即可,由于这个步骤只经过一个数学上的映射,也可以理解为一个数学计算,因此查询某一个特定的key-value键值对的时间复杂度为O(1)。
举个例子(只是帮助理解),还是上述的list_a和list_b。我们将所有的元素当作key, value可以随意选取,假设映射规则是 key / 11,那么list_a中的11映射为1,22映射为2,33映射为3,44映射为4,55映射为5,list_b中的22映射为2,11映射为1,55映射为5,44映射为4,33映射为3.于是,只需要一次遍历,我们就能知道list_a中的元素和list_b中的元素是一样的。 - HashMap的java实现(仍然以list_a和list_b为例)
HashMap在java.utl.HashMap包中,导入只需要import java.utl.HashMap即可,也可直接import java.utl.*(不推荐),使用eclipse的同学也可以快捷键ctrl + shift + o导包。
3.1 构造函数
HashMap<Integer,Integer> hm_a = new HashMap<Integer,Integer>();
Map<Integer,Integer> hm_b = new HashMap<Integer,Integer>();本人更多用第二种,父类引用指向子类对象,但是需要单独导Map的包
3.2 相关方法
hm_a.push(11,1);
hm_a.push(22,1);
hm_a.push(33.1);
hm_a.push(44,1);
hm_a.push(55,1);
hm_b.push(22,1);
hm_b.push(11,1);
hm_b.push(55.1);
hm_b.push(44,1);
hm_b.push(33,1);
我们就构建好了两个hashmap并将元素放入了hashmap中,由于value在此无关紧要,于是都设置为1。当我们输入 boolean b = hm_a.equals(hm_b)时,会发现输出b为true,即两个hashmap所有元素一样。
其他常用方法:
boolean isEmpty() :判断是否为空
boolean containsKey(object key):是否存在键为key的映射
boolean containsValue(object value):是否存在值为value的映射
v get(object key):获取键为key的映射
int size():返回键值对的个数
v remove(object key):删除键为key的键值对
boolean remove(object key, object value):删除指定键值对
遍历可采用迭代器,也可采用增强for循环