1.概念
Map
和
set
是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关
。
我们常见的搜索方式有:直接遍历和二分查找。但是这两种排序更合适静态类型的查找,也就是说不会对所排区间进行插入、删除等操作,而现实中的查找,更多的会涉及到插入、删除这些操作,比如通讯录。那么我们就会需要动态查找,即使用Map和Set。
2.模型
一般把搜索的数据称为关键字(
Key
),和关键字对应的称为值(
Value
),将其称之为
Key-value
的键值对,所以模型会有两种:
1.
纯
key
模型
,比如:
○ 有一个英文词典,快速查找一个单词是否在词典中
2.
Key-Value
模型
,比如:
○ 统计文件中每个单词出现的次数,统计结果是每个单词都有与其对应的次数:<
单词,单词出现的次数>
而
Map
中存储的就是
key-value
的键值对,
Set
中只存储了
Key
。
3.Map的使用
Map
是一个接口类,该类没有继承自
Collection
,该类中存储的是
<K,V>
结构的键值对,并且
K
一定是唯
一的,不能重复
。
Map.Entry<K, V>
是
Map
内部实现的用来存放
<key, value>
键值对映射关系的内部类
,该内部类中主要提供了<key, value>
的获取,
value
的设置以及
Key
的比较方式。
注意:
Map.Entry<K,V>
并没有提供设置
Key
的方法
注意:
1.
Map
是一个接口,不能直接实例化对象
,如果
要实例化对象只能实例化其实现类
TreeMap
或者
HashMap
2.
Map
中存放键值对的
Key
是唯一的,
value
是可以重复的
3.
在
Map
中插入键值对时,
key
不能为空,否则就会抛
NullPointerException
异常
,但是
value
可以为空
4.
Map
中的
Key
可以全部分离出来,存储到
Set
中
来进行访问
(
因为
Key
不能重复
)
。
5.
Map
中的
value
可以全部分离出来,存储在
Collection
的任何一个子集合中
(value
可能有重复
)
。
6. Map
中键值对的
Key
不能直接修改,
value
可以修改,如果要修改
key
,只能先将该
key
删除掉,然后再来进行重新插入。
7. TreeMap
和
HashMap
的区别:
4.TreeMap的使用案例
import java.util.TreeMap;
import java.util.Map;
public static void TestMap1(){
Map<String, String> m = new TreeMap<>();
// put(key, value):插入key-value的键值对
// 如果key不存在,会将key-value的键值对插入到map中,返回null
m.put("林冲", "豹子头");
m.put("鲁智深", "花和尚");
m.put("武松", "行者");
m.put("宋江", "及时雨");
String str = m.put("李逵", "黑旋风");
System.out.println(m.size());
System.out.println(m);
// put(key,value): 注意key不能为空,但是value可以为空
// key如果为空,会抛出空指针异常
//m.put(null, "花名");
str = m.put("无名", null);
System.out.println(m.size());
// put(key, value):
// 如果key存在,会使用value替换原来key所对应的value,返回旧value
str = m.put("李逵", "铁牛");
// get(key): 返回key所对应的value
// 如果key存在,返回key所对应的value
// 如果key不存在,返回null
System.out.println(m.get("鲁智深"));
System.out.println(m.get("史进"));
//GetOrDefault(): 如果key存在,返回与key所对应的value,如果key不存在,返回一个默认值
System.out.println(m.getOrDefault("李逵", "铁牛"));
System.out.println(m.getOrDefault("史进", "九纹龙"));
System.out.println(m.size());
System.out.println(m.containsKey("林冲"));
System.out.println(m.containsKey("史进"));
// containValue(value): 检测value是否包含在Map中,时间复杂度: O(N)
// 因为TreeMap是按照Key进行组织的,因此查找value时候就需要整体遍历
// 找到返回true,否则返回false
System.out.println(m.containsValue("豹子头"));
System.out.println(m.containsValue("九纹龙"));
// 打印所有的key
// keySet是将map中的key防止在Set中返回的
for(String s : m.keySet()){
System.out.print(s + " ");
}
System.out.println();
// 打印所有的value
// values()是将map中的value放在collect的一个集合中返回的
for(String s : m.values()){
System.out.print(s + " ");
}
System.out.println();
// 打印所有的键值对
// entrySet(): 将Map中的键值对放在Set中返回了
for(Map.Entry<String, String> entry : m.entrySet()){
System.out.println(entry.getKey() + "--->" + entry.getValue());
}
System.out.println();
}
5. Set的说明
注意:
1. Set
是继承自
Collection
的一个接口类
2. Set
中只存储了
key
,并且要求
key
一定要唯一
3. Set
的底层是使用
Map
来实现的,其使用
key
与
Object
的一个默认对象作为键值对插入到
Map
中的
4. Set
最大的功能就是对集合中的元素进行去重
5.
实现
Set
接口的常用类有
TreeSet
和
HashSet
,还有一个
LinkedHashSet
,
LinkedHashSet
是在HashSet的基础上维护了一个双向链表来记录元素的插入次序。
6. Set
中的
Key
不能修改,如果要修改,先将原来的删除掉,然后再重新插入
7. Set
中不能插入
null
的
key
。
8. TreeSet
和
HashSet
的区别:
6.TreeSet的使用
import java.util.TreeSet;
import java.util.Iterator;
import java.util.Set;
public static void TestSet(){
Set<String> s = new TreeSet<>();
// add(key): 如果key不存在,则插入,返回ture
// 如果key存在,返回false
boolean isIn = s.add("apple");
s.add("orange");
s.add("peach");
s.add("banana");
System.out.println(s.size());
System.out.println(s);
isIn = s.add("apple");
// add(key): key如果是空,抛出空指针异常
//s.add(null);
// contains(key): 如果key存在,返回true,否则返回false
System.out.println(s.contains("apple"));
System.out.println(s.contains("watermelen"));
// remove(key): key存在,删除成功返回true
// key不存在,删除失败返回false
// key为空,抛出空指针异常
s.remove("apple");
System.out.println(s);
s.remove("watermelen");
System.out.println(s);
// 抛出空指针异常
// s.remove(null);
Iterator<String> it = s.iterator();
while(it.hasNext()){
System.out.print(it.next() + " ");
}
System.out.println();
}