52-Map和Set(实现类HashMap/TreeMap/HashSet/TreeSet )

Posted hyperNZ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了52-Map和Set(实现类HashMap/TreeMap/HashSet/TreeSet )相关的知识,希望对你有一定的参考价值。

目录

1.搜索

1.1.概念及场景

1.1.1.概念

1.1.2.场景

1.2.模型

1.2.1.纯key模型-Set

1.2.2.key-value模型-Map

1.3.关系图

2.Map的使用

2.1.说明

2.2.Map的常用操作(增、删、改、查、遍历)

2.2.1.Map集合内部的元素之间的先后顺序与插入顺序关系不大。

2.2.2.Map集合中插入和修改元素——put

2.2.3.Map集合中根据key取得value——get

2.2.4.Map集合中删除元素——remove

2.2.5.Map集合的遍历——Entry

2.2.6.Map集合的搜索操作——contains

2.3.注意

3.Set的使用

3.1.说明

3.2.方法

3.3.注意


1.搜索

1.1.概念及场景

1.1.1.概念

Map和Set是一种专门用来进行搜索的容器/数据结构,其搜索的效率与其具体的实例化子类有关。

1.1.2.场景

  • 之前:静态类型查找(一般不会对区间进行插入和删除操作)
  1. 直接遍历:时间复杂度O(N),元素如果比较多,效率会很慢。
  2. 二分查找:时间复杂度O(log2N),但搜索前必须要求序列是有序的。
  • 本节:动态类型查找(可能在查找时进行一些插入和删除操作)
  1. 根据姓名查询考试成绩。
  2. 通讯录,根据姓名查询联系方式。
  3. 不重复集合,即需要先搜索关键字是否已经在集合中。

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中非常高效:

  1. HashMap中接近O(1)时间复杂度,数组查找。
  2. 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.注意

  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的区别:
Map底层实现TreeMapHashMap
底层结构红黑树哈希桶
插入/删除/查找的时间复杂度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.注意

  1. Set是继承自Collection的一个接口类。
  2. Set中只存储了key,key唯一。
  3. Set的底层是用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中。
  4. Set最大的功能:对集合中元素去重。
  5. 实现Set接口的常用类有TreeSet和HashSet,还有一个LinkedHashSet(是在HashSet的基础上维护了一个双向链表来记录元素的插入次序)。
  6. Set中的key不能修改,若要改,将原来的删去,再重新插入。
  7. Set中不能插入null的key。
  8. TreeSet和HashSet的区别:
Set底层结构TreeSetHashSet
底层结构红黑树哈希桶
插入/删除/查找的时间复杂度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 )的主要内容,如果未能解决你的问题,请参考以下文章

Java 集合类 List Set Map 线程安全

Map和Set的联系

Set的常用实现类HashSet和TreeSet

Set接口及其实现类HashSetTreeSet的底层结构与区别

java的集合类(MapList与Set比较)

Set接口HashSet实现类