前言:
大家好,我是良辰丫,今天我们来学习Map相关知识 , 认识搜索树的模型 , 通过源码以及代码深入了解Map , 还在等什么,赶快与良辰一起去探索Map的海洋吧。💞💞💞
🧑个人主页:良辰针不戳
📖所属专栏:java数据结构
🍎励志语句:生活也许会让我们遍体鳞伤,但最终这些伤口会成为我们一辈子的财富。
💦期待大家三连,关注,点赞,收藏。
💌作者能力有限,可能也会出错,欢迎大家指正。
💞愿与君为伴,共探Java汪洋大海。
目录
1. 简单认识一下搜索的模型
我们往往把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称之为Key-value的键值对,我们常见的模型有下面两种.
- 纯 key 模型,比如:我们可以通过关键词key可以查看该数据是否包含在里面.比如我们在通讯录里面我们可以通过查找名字,看该名字是否在通讯录里面.
- Key-Value 模型,也就是通过key找到对应的value,还是拿通讯录举例,我们可以通过某个人的名字快速定位到他的电话号码(在这里我们假设\通讯录一个名字只存储对应的一个电话号码) , 其中Map就是我们常见的key-value模型
2. 走进Map的学习
- Map是一个接口类,该类没有继承自Collection,该类中存储的是<K,V>结构的键值对,并且K一定是唯一的,不能重复。
- 我们又见到了我们在学习集合的时候的图,这张图至关重要,它记录着各个集合类与接口之间的联系.
2.1 源码简单分析Map
Map是一个键值对为了让大家更加深刻的认识一下Map,我们来简单分析一下它的源码.
- 通过上面的源码,我们发现Map是一个接口.
- 接口是一种纯粹的抽象定义,它不能被实例化。但是,可以通过类来实现接口,并使用实现类来创建接口的对象.
- 到了这里我们又发现接口是通过抽象类实现的.
- 抽象类也不能完成实例化,要通过子类继承,通过子类完成实例化的相关操作.
下面是我们使用哈希Map的正确写法,只能通过子类实例化.
2.2 Map常见的方法
方法 | 说明 |
---|---|
V get(Object key) | 返回 key 对应的 value |
V getOrDefault(Object key, V defaultValue) | 返回 key 对应的 value,key 不存在,返回默认值 |
V put(K key, V value) | 设置 key 对应的 value |
V remove(Object key) | 删除 key 对应的映射关系 |
Set keySet() | 返回所有 key 的不重复集合 |
Collection values() | 返回所有 value 的可重复集合 |
Set<Map.Entry<K, V>> entrySet() | 返回所有的 key-value 映射关系 |
boolean containsValue(Object value) | 判断是否包含 value |
2.3 通过代码认识Map
2.3.1 TreeMap
TreeMap的底层是一个红黑树 , 并且它是由SortedMap实现的,是可比较的.
public static void main(String[] args) {
Map<String,Integer> map = new TreeMap<>();
map.put("c",2);
map.put("b",2);
map.put("a",2);
System.out.println(map);
}
- 然后我们看一下打印结果 , 我们会惊奇的发现 , 我们存放的顺序是cba,但是打印的时候优顺序为abc.
- 这是因为它的底层有一个比较器 , 有一定的比较规则.
- 也就是说在MapTree里面 , 我们的key必须是可比较的 , 接下来我们就去证明一下 .
- 我们创一个User类 , 把User当成key.
- 我们在写代码的时候没有任何关于提示报错的信息.
- 但是当我们运行的时候就会报错 , 因为在我们的User类中 , 我们没有给它指定比较规则 , 如果我们给它搞一个比较器 , 它就不会报错了 , 在这里我就不搞比较器了 , 如果大家想去了解 , 就会看我的比较器文章
- 比较器链接: 比较器
2.3.2 根据key值得到value值
- 我们还可以根据我们的key值得到我们的value值.
- 因为我们的key是可比较的 , 这样它才是一颗搜索树 .
public static void main(String[] args) {
Map<String,Integer> map = new TreeMap<>();
map.put("c",3);
map.put("b",2);
map.put("a",1);
int a = map.get("a");
System.out.println(a);
}
2.3.3 getOrDefault默认值方法
在我们的表里找不到key值 , 我们可以使用getOrDefault , 找不到的时候我们可以给它一个默认值 .
2.2.4 获取关键字key
public static void main(String[] args) {
Map<String,Integer> map = new TreeMap<>();
map.put("c",3);
map.put("b",2);
map.put("a",1);
Set<String> set = map.keySet();
System.out.println(set);
}
2.2.5 获取values值
public static void main(String[] args) {
Map<String,Integer> map = new TreeMap<>();
map.put("c",3);
map.put("b",2);
map.put("a",1);
Collection<Integer> collection = map.values();
System.out.println(collection);
}
2.2.6 遍历Map集合
public static void main(String[] args) {
Map<String,Integer> map = new TreeMap<>();
map.put("c",3);
map.put("b",2);
map.put("a",1);
Set<Map.Entry<String,Integer>> set = map.entrySet();
System.out.println(set);
}
遍历我们的map的方式
public static void main(String[] args) {
Map<String,Integer> map = new TreeMap<>();
map.put("c",3);
map.put("b",2);
map.put("a",1);
Set<Map.Entry<String,Integer>> set = map.entrySet();
System.out.println(set);
for(Map.Entry<String,Integer> entry:set){
System.out.println(entry.getKey()+" : "+entry.getValue());
}
}
我们一般的集合遍历一定要实现迭代器Iterable , 但是我们的map是一个单独的接口 , 和Iterable没有关系
4. 小结
- Map是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类TreeMap或者HashMap
- Map中存放键值对的Key是唯一的,value是可以重复的
- 在TreeMap中插入键值对时,key不能为空,否则就NullPointerException异常,value可以为空。但是HashMap的key和value都可以为空。因为TreeMap是搜索树 , 它的key值是可比较的 , 如果为null的话就不可以比较了.
- Map中的Key可以全部分离出来,存储到Set中来进行访问(因为Key不能重复)。
- Map中的value可以全部分离出来,存储在Collection的任何一个子集合中(value可能有重复, 所以用这个)。
- Map中键值对的Key不能直接修改,value可以修改,如果要修改key,只能先将该key删除掉,然后再来进行重新插入。