52-Map和Set(实现类HashMap/TreeMap/HashSet/TreeSet )
Posted hyperNZ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了52-Map和Set(实现类HashMap/TreeMap/HashSet/TreeSet )相关的知识,希望对你有一定的参考价值。
目录
2.2.1.Map集合内部的元素之间的先后顺序与插入顺序关系不大。
1.搜索
1.1.概念及场景
1.1.1.概念
Map和Set是一种专门用来进行搜索的容器/数据结构,其搜索的效率与其具体的实例化子类有关。
1.1.2.场景
- 之前:静态类型查找(一般不会对区间进行插入和删除操作)
- 直接遍历:时间复杂度O(N),元素如果比较多,效率会很慢。
- 二分查找:时间复杂度O(log2N),但搜索前必须要求序列是有序的。
- 本节:动态类型查找(可能在查找时进行一些插入和删除操作)
- 根据姓名查询考试成绩。
- 通讯录,根据姓名查询联系方式。
- 不重复集合,即需要先搜索关键字是否已经在集合中。
Map和Set是一种适合动态查找的集合容器。
1.2.模型
一般把搜索的数据称为关键字(key),和关键字对应的称为值(value),将其称之为key-value键值对。
1.2.1.纯key模型-Set
- 快速查找一个单词是否在词典中。
- 快速查找一个名字是否在通讯录中。
1.2.2.key-value模型-Map
- 统计文件中每个单词出现的次数,结果:<单词,单词出现的次数>。
- 每个梁山好汉都有自己的江湖绰号。
1.3.关系图
2.Map的使用
2.1.说明
Map是一个接口类,该类没有继承自Collection,该类中存储的是<k, v>结构的键值对,k一定唯一不重复,value可重复。
2.2.Map的常用操作(增、删、改、查、遍历)
2.2.1.Map集合内部的元素之间的先后顺序与插入顺序关系不大。
而线性表元素顺序基本都是按照插入顺序来决定的。
例:
List<Integer> list = new ArrayList<>(); list.add(1); //index = 0 list.add(2); //index = 1
import java.util.HashMap;
import java.util.Map;
/**
* Map的常用操作
*/
public class MapTest
public static void main(String[] args)
Map<String, String> map = new HashMap<>();
map.put("宋江", "及时雨");
map.put("李逵", "黑旋风");
map.put("吴用", "军师");
System.out.println(map);
2.2.2.Map集合中插入和修改元素——put
put(key, value)
- 若key不存在,则将要插入的键值对key-value作为新节点插入到Map集合中。
- 若key存在,则更新对应的value值为新的value,新value覆盖旧value,返回修改前的元素值。
public class MapTest
public static void main(String[] args)
Map<String, String> map = new HashMap<>();
map.put("宋江", "及时雨");
map.put("李逵", "黑旋风");
map.put("吴用", "军师");
System.out.println(map);
System.out.println(map.put("吴用", "智多星"));
System.out.println(map);
2.2.3.Map集合中根据key取得value——get
- get(key):返回传入key对应的value值,若key不存在,返回null。
- getOrDefault(key, defaultValue):根据key取得对应的value值,若key不存在,返回默认值。
System.out.println(map.get("李逵"));
System.out.println(map.get("武松"));
System.out.println(map.getOrDefault("张三", "好闺蜜"));
2.2.4.Map集合中删除元素——remove
V remove(Object key);
返回删除的键值对的value值,若不存在返回null。
System.out.println(map.remove("宋江"));
System.out.println(map.remove("张三"));
2.2.5.Map集合的遍历——Entry
不推荐,不到万不得已,不要使用这几个方法。
- Collection接口及其子类可以很方便地使用for-each循环进行遍历,但Map和Collection集合没有任何关系。
- 要遍历Map集合,就需要把Map集合转为Set集合,然后进行遍历操作。
- Map集合是存key=value键值对,Set集合是存单个不重复元素。
- 需要把key和value打包成一个对象,然后用Set存储这个对象(此对象的类型为Map.Entry)(Entry是Map的一个个实体/键值对对象)。
①Map.Entry<K,V>
Map.Entry<K,V>是Map内部实现的用来存放<key, value>键值对映射关系的内部类/内部接口(interface Map.Entry<K, V>)。该内部类中主要提供了<key, value>的获取,value的设置以及key的比较方式,并没有提供设置key的方法。
方法 | 解释 |
K getKey() | 返回entry中的key |
V getValue() | 返回entry中的value |
V setValue(V value) | 将键值对中的value替换为指定value |
a.获取所有的key的集合(返回值不同)
Set<K> keySet();
b.获取所有的value的集合(返回值不同)
Collection<V> values();
c.将Map集合转为Set集合
Set<Map.Entry<K, V>> entrySet();
//获取Map中所有的key值
Set<String> strings = map.keySet(); //keySet选中,Alt + Enter快捷生成临时变量接收返回值
//获取Map中所有的value值
Collection<String> values = map.values();
System.out.println(strings);
System.out.println(values);
②遍历Map集合
//Map -> Set
Set<Map.Entry<String, String>> entries = map.entrySet();
//for-each遍历Set集合
for(Map.Entry<String, String> entry : entries)
System.out.println(entry.getKey() + "=" + entry.getValue());
2.2.6.Map集合的搜索操作——contains
contains()方法在Map中非常高效:
- HashMap中接近O(1)时间复杂度,数组查找。
- TreeMap中接近O(logn)时间复杂度,二分查找。
- boolean containsKey(Object key);
- boolean containsValue(Object value);
System.out.println(map.containsKey("吴用"));
System.out.println(map.containsValue("及时雨"));
System.out.println(map.containsValue("学神"));
2.3.注意
- Map是一个接口,不能直接实例化对象,如果要实例化对象,只能实例化其实现类TreeMap或者HashMap。
- Map中存放键值对的key是唯一的,value可重复。
- 在Map中插入键值对时,key不能为空,否则会抛NullPointerException异常,但value可以为空。
- Map的key可以全部分离出来,存储到Set中进行访问。(key不可重复)
- Map的value可以全部分离出来,存储到Collection的任何一个子集合中。(value可重复)
- Map中的键值对的key不能直接修改,value可修改。如果要修改key,只能先将key删除掉,然后再重新插入。
- TreeMap何HashMap的区别:
Map底层实现 | TreeMap | HashMap |
底层结构 | 红黑树 | 哈希桶 |
插入/删除/查找的时间复杂度 | O(log2n) | O(1) |
是否有序 | 关于key有序 | 无序 |
线程安全 | 不安全 | 不安全 |
插入/删除/查找的区别 | 需要进行元素比较,key必须能够比较,否则抛出ClassCastException异常 | 通过哈希函数计算哈希地址,自定义类型需要覆写equals和hashCode方法 |
应用场景 | 需要key有序的场景下 | key是否有序不关心,需要更高的时间性能 |
3.Set的使用
3.1.说明
Set集合的使用等同于List,都是Collection的子接口。
最常用的Set集合场景,用在元素去重。
3.2.方法
方法 | 解释 |
boolean add(E e) | 添加元素,但重复元素不会被添加成功 |
void clear() | 清空集合 |
boolean contains(Object o) | 判断o是否在集合中 |
Iterator<E> iterator() | 返回迭代器 |
boolean remove(Object o) | 删除集合中的o |
int size() | 返回set中元素的个数 |
boolean isEmpty() | 检测set是否为空,空返回true,否则返回false |
Object[] toArray() | 将set中的元素转换为数组返回 |
boolean containsAll(Collection<?> c) | 集合c中的元素是否在set中全部存在,是返回true,否返回false |
boolean addAll(Collection<?extends E> c) | 将集合c中的元素添加到set中,可以达到去重的效果 |
3.3.注意
- Set是继承自Collection的一个接口类。
- Set中只存储了key,key唯一。
- Set的底层是用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中。
- Set最大的功能:对集合中元素去重。
- 实现Set接口的常用类有TreeSet和HashSet,还有一个LinkedHashSet(是在HashSet的基础上维护了一个双向链表来记录元素的插入次序)。
- Set中的key不能修改,若要改,将原来的删去,再重新插入。
- Set中不能插入null的key。
- TreeSet和HashSet的区别:
Set底层结构 | TreeSet | HashSet |
底层结构 | 红黑树 | 哈希桶 |
插入/删除/查找的时间复杂度 | O(log2n) | O(1) |
是否有序 | 关于key有序 | 不一定有序 |
线程安全 | 不安全 | 不安全 |
插入/删除/查找的区别 | 按红黑树的特性来插/删,key必须比较,否则会抛出ClassCastException异常 | 先计算key哈希地址,然后进行插入和删除。自定义类型需要覆写equals和hashCode方法。 |
应用场景 | 需要key有序场景下 | key是否有序不关心,需要更高的时间性能 |
Map和Set的联系
Java中的集合
Java中的集合包括三大类,它们是Set、List和Map,它们都处于java.util包中,Set、List和Map都是接口,它们有各自的实现类。Set的实现类主要有HashSet和TreeSet,List的实现类主要有ArrayList,Map的实现类主要有HashMap和TreeMap。
Map中,key能否重复,如果重复?会有什么现象?
键可以重复,不会报错,只是在取的时候,先存进map中的值会被后存进map的值覆盖掉。
Set和Map的集合类名称相似,有没有内在的联系?
Map所有的key其实是一个Set,Map所有的value是某种可以存储重复数据的集合,而把key组成的Set中的元素和value组成的某种的集合中的元素一一对应起来后,就组成了一个Map。
以上是关于52-Map和Set(实现类HashMap/TreeMap/HashSet/TreeSet )的主要内容,如果未能解决你的问题,请参考以下文章