Map_Set
一、基本思路
1. 是用来做什么的?
1.1 以前
回顾之前我们都学过数据结构,一般遇到搜索的问题我们都会想到的是直接遍历或者是二分查找,直接遍历虽然操作比较简单,但是如果遇到的数据比较多的话,其效率非常低下;而二分查找又要求序列是有序的,这两种方式都比较适合于静态类型的查找,一般不会对区间进行插入和删除操作,但是现实中的查找例如:
a.通讯录查找,根据姓名查找联系方式并进行修改;
b.在Excel中根据学号查找自己的信息并补充信息;
在查找过程中可能伴随着补充新的数据信息或者是删除修改操作,即动态查找,此时直接遍历及二分查找就不太合适了,而Map和Set就是来解决这样的弊端的!
1.2 现在
Map和Set是一种专门用来进行搜索的容器或者数据结构;
核心目标: Map和Set主要是为了查找效率的提升,因此在以后的实践过程中只要是有搜索的场景,就要想到用Map和Set。
2. 两种模型
Key:关键字;
Value:关键字对应的值。
1.1 纯Key模型
Set中只存储了Key,例如在手机通讯录中查找某个姓名在不在里面;
1.2 Key-Value模型
Map中存储的就是Key-Value的键值对,例如在一篇阅读理解中每个单词及其对应出现的次数:<单词,单词出现的次数>
3. 注意点
- key值一定是唯一的,如果key值一样,那么value就得更新;
- 打印顺序不一定是put的顺序,因为put是按照某种规则来存储的;
- map不能使用迭代器进行打印;
- key值不可修改,但是value可以修改。
二、Map的使用
1. 基本说明
Map是一个接口类,并且该类没有继承自Collection,该类中存储的是<Key,Value>键值对,Key一定是唯一的。
2. 常用方法
关于Map的使用方法我以实例的方式进行讲解,代码及其注解如下:
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("没羽箭","张清");
map.put("黑旋风","李逵");
map.put("霹雳火","秦明");
String str = map.get("黑旋风");//返回key对应的value
System.out.println(str);//李逵
String str1 = map.getOrDefault("及时雨","宋江");
//返回key对应的value,如果key不存在,则返回默认值。
System.out.println(map.get("及时雨"));//null
String str2 = map.put("及时雨","宋江");//设置key对应的value
System.out.println(map.get("及时雨"));//宋江
map.remove("霹雳火");//删除key对应的映射关系
System.out.println(map.get("霹雳火"));//null
System.out.println(map.keySet());//返回所有的key,注意是不重复的集合
//结果:[黑旋风, 没羽箭, 及时雨]
System.out.println(map.values());//返回所有的value的值,注意可以是重复的集合
//结果:[李逵, 张清, 宋江]
System.out.println(map.entrySet());//返回所有的key-value
//结果:[黑旋风=李逵, 没羽箭=张清, 及时雨=宋江]
System.out.println(map.containsKey("及时雨1"));//判断是否包含key 结果:false
System.out.println(map.containsValue("宋江"));//判断是否包含value 结果:true
}
注意点
- 在map中插入键值对时,key不能为空,否在会抛出异常(NullPointerException),但是value值可以是空的;
- Map中的Key可以全部分离出来,存储到Set中来进行访问(Key不能重复);
- Map中的value可以全部分离出来,存储在Collection的任何一个子集合中(value可能有重复);
- Map中键值对的Key不能直接修改,value可以修改,如果要修改key,只能先将该key删除掉,然后再来进行重新插入。
3. Map.Entry的使用
Map.Entry<k,v>是Map内部实现的用来存放<Key,Value>键值对映射关系的内部类, 该内部类中主要提供了<Key,Value>的获取、Value的设置以及Key的比较方式。实现方法如下:
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("没羽箭","张清");
map.put("黑旋风","李逵");
map.put("霹雳火","秦明");
Set<Map.Entry<String,String>> entrySet = map.entrySet();
for (Map.Entry<String,String> entry :entrySet) {
System.out.println("key: "+entry.getKey() + ", val: "+entry.getValue());
}
}
输出结果:
注意: Map.Entry<K,V>并没有提供设置Key的方法!
三、Set的使用
1. 基本说明
Set和Map主要的差别:Set是继承自Collection的接口类,Set中只存储了Key。
2. 常用方法
关于Map的使用方法我以实例的方式进行讲解,代码及其注解如下:
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.add("C");
Iterator<String> it = set.iterator();//返回迭代器
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println(set.size());//返回set中元素的个数
System.out.println(set.contains("A"));//判断集合中的元素
set.remove("B");//删除集合中的B
System.out.println(set.contains("B"));
Object[] array = set.toArray();//将set中的元素转换成数组返回
//注意在java当中数组不能进行整体的转换,因此不可以写成如下:
//String[] strings = (String[])set.toArray();
for (Object str : array) {
System.out.println(str);
}
set.clear();//清空集合
System.out.println(set.size());
}
3. 注意点
- 在java当中数组不能进行整体的转换;
- Set中只存储了key,并且要求key一定要唯一;
- Set的底层是使用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中的;
- Set最大的功能就是对集合中的元素进行去重,下面的练习题中会有所呈现;
- Set中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入;
- Set中不能插入null的key。
四、实践
1. 练习题1 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次;找出那个只出现了一次的元素。
链接:只出现一次的数字
2. 练习题2 宝石与石子
给你一个字符串 jewels 代表石头中宝石的类型,另有一个字符串 stones 代表你拥有的石头;stones 中每个字符代表了一种你拥有的石头的类型,想知道拥有的石头中有多少是宝石?(字母区分大小写,因此 “a” 和 “A” 是不同类型的石头)
链接:宝石与石子