MultiValueMap到底是什么
MultiValueMap是什么?
要知道MultiValueMap是什么,我们首先说一个问题,那就是Map,Map有一个特性,那就是一个k-v,并且还是只能是一个v,一个k,那我们有的时候需要存储多个v咋办?比如我们想实现权限系统用多个v是不是很方便。
MultiValueMap 这个本身是Spring里提供的一个多值Map,你可以理解为Map
public interface MultiValueMap<K, V> extends Map<K, List<V>> {
}
有的小朋友说,那Map可以指定一个实体类进行存储啊,没错,可以,但是请问如果你连续调用两次put或者add试试!是不是覆盖了?
既然要实现一个map,我们起码要实现添加删除,修改吧!看我下边我们的雏形变成现在这样!
MultiValueMap接口
public interface MultiValueMap<K, V> extends Map<K, List<V>> {
/**
* 根据Key获取值,并制定参数不能为空
*/
@Nullable
V getFirst(K key);
/**
* 根据Key设置Value
*/
void add(K key, @Nullable V value);
/**
* 根据Key批量设置
*/
void addAll(K key, List<? extends V> values);
/**
* 直接批量添加MultiValueMap类型
*/
void addAll(org.springframework.util.MultiValueMap<K, V> values);
/**
* 如果不存在Key才添加
*/
default void addIfAbsent(K key, @Nullable V value) {
if (!containsKey(key)) {
add(key, value);
}
}
/**
* 为指定 key 赋值。该 key 原来的值会被全部覆盖掉。
*/
void set(K key, @Nullable V value);
/**
* 批量赋值
*/
void setAll(Map<K, V> values);
/**
* 返回一个普通的 Map,该 Map 中仅包含每个 key 对应的第一个 value
*/
Map<K, V> toSingleValueMap();
}
光有接口是无法使用的,我们来看看Spring有哪些实现类
系统有哪些实现
- org.springframework.http.HttpHeaders
- org.springframework.http.server.reactive.JettyHeadersAdapter
- org.springframework.util.LinkedMultiValueMap
- org.springframework.util.CollectionUtils.MultiValueMapAdapter
- org.springframework.http.server.reactive.NettyHeadersAdapter
- org.springframework.http.ReadOnlyHttpHeaders 这个继承类HttpHeaders
- org.springframework.http.server.ServletServerHttpResponse.ServletResponseHttpHeaders 这个继承类HttpHeaders
- org.springframework.http.server.reactive.TomcatHeadersAdapter
- org.springframework.http.server.reactive.UndertowHeadersAdapter
实现分析
咱们来看看org.springframework.util.LinkedMultiValueMap,用以点带面的讲解,帮助大家理解。
public class LinkedMultiValueMap<K, V> implements MultiValueMap<K, V>, Serializable, Cloneable {
private static final long serialVersionUID = 3801124242820219131L;
private final Map<K, List<V>> targetMap;
/**
* 初始化一个有序的LinkedHashMap
*/
public LinkedMultiValueMap() {
this.targetMap = new LinkedHashMap<>();
}
/**
* 初始化LinkedHashMap长度
*/
public LinkedMultiValueMap(int initialCapacity) {
this.targetMap = new LinkedHashMap<>(initialCapacity);
}
/**
* 浅拷贝构造方法,不明白暂且理解为赋值吧!
*/
public LinkedMultiValueMap(Map<K, List<V>> otherMap) {
this.targetMap = new LinkedHashMap<>(otherMap);
}
/**
* 根据Key返回第一个Value,Key不能为空
*/
@Override
@Nullable
public V getFirst(K key) {
List<V> values = this.targetMap.get(key);
return (values != null && !values.isEmpty() ? values.get(0) : null);
}
/**
* 指定Key增加Value
*/
@Override
public void add(K key, @Nullable V value) {
List<V> values = this.targetMap.computeIfAbsent(key, k -> new LinkedList<>());
values.add(value);
}
/***
* 根据Key批量提前加List
*/
@Override
public void addAll(K key, List<? extends V> values) {
List<V> currentValues = this.targetMap.computeIfAbsent(key, k -> new LinkedList<>());
currentValues.addAll(values);
}
/**
* 把多值Map添加到另一个多值Map
*/
@Override
public void addAll(MultiValueMap<K, V> values) {
for (Entry<K, List<V>> entry : values.entrySet()) {
addAll(entry.getKey(), entry.getValue());
}
}
/**
* 把值添加到某个Key中
*/
@Override
public void set(K key, @Nullable V value) {
List<V> values = new LinkedList<>();
values.add(value);
this.targetMap.put(key, values);
}
/**
* 把Map添加到多值Map
*/
@Override
public void setAll(Map<K, V> values) {
values.forEach(this::set);
}
/**
* 字符串输出多值Map
*/
@Override
public Map<K, V> toSingleValueMap() {
LinkedHashMap<K, V> singleValueMap = new LinkedHashMap<>(this.targetMap.size());
this.targetMap.forEach((key, values) -> {
if (values != null && !values.isEmpty()) {
singleValueMap.put(key, values.get(0));
}
});
return singleValueMap;
}
/**
* 获取多值Map尺寸
*/
@Override
public int size() {
return this.targetMap.size();
}
/**
* 判断多值Map是不是为空
*/
@Override
public boolean isEmpty() {
return this.targetMap.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return this.targetMap.containsKey(key);
}
/**
* 判断Key是否存在
*/
@Override
public boolean containsValue(Object value) {
return this.targetMap.containsValue(value);
}
/**
* 根据Key获取List
*/
@Override
@Nullable
public List<V> get(Object key) {
return this.targetMap.get(key);
}
/**
* 添加元素
*/
@Override
@Nullable
public List<V> put(K key, List<V> value) {
return this.targetMap.put(key, value);
}
/**
* 删除元素
*/
@Override
@Nullable
public List<V> remove(Object key) {
return this.targetMap.remove(key);
}
@Override
public void putAll(Map<? extends K, ? extends List<V>> map) {
this.targetMap.putAll(map);
}
/**
* 清空所有
*/
@Override
public void clear() {
this.targetMap.clear();
}
/**
* 获取key
*/
@Override
public Set<K> keySet() {
return this.targetMap.keySet();
}
/**
* 获取值得集合
*/
@Override
public Collection<List<V>> values() {
return this.targetMap.values();
}
@Override
public Set<Entry<K, List<V>>> entrySet() {
return this.targetMap.entrySet();
}
/**
* 深度复制
*/
public LinkedMultiValueMap<K, V> deepCopy() {
LinkedMultiValueMap<K, V> copy = new LinkedMultiValueMap<>(this.targetMap.size());
this.targetMap.forEach((key, value) -> copy.put(key, new LinkedList<>(value)));
return copy;
}
/**
* 浅克隆
*/
@Override
public LinkedMultiValueMap<K, V> clone() {
return new LinkedMultiValueMap<>(this);
}
/**
* equals()相等的两个对象,hashcode()一定相等;
* 反过来:hashcode()不等,一定能推出equals()也不等;
* hashcode()相等,equals()可能相等,也可能不等。
*/
@Override
public boolean equals(@Nullable Object obj) {
return this.targetMap.equals(obj);
}
@Override
public int hashCode() {
return this.targetMap.hashCode();
}
/**
* 字符串打印
*/
@Override
public String toString() {
return this.targetMap.toString();
}
}
使用
package com.pv3.springboot_base.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
@RestController
public class MutilValueController {
@RequestMapping(value = "/mutilvalue")
public String demo() {
// 声明一个LinkeMultiValue
LinkedMultiValueMap<Object, Object> linkedMultiValueMap = new LinkedMultiValueMap<>(16);
linkedMultiValueMap.add("姓名", "李四");
// {姓名=[李四]}
System.out.println(linkedMultiValueMap);
linkedMultiValueMap.add("姓名", "王五");
// {姓名=[李四, 王五]}
System.out.println(linkedMultiValueMap);
linkedMultiValueMap.add("性格", "温柔贤惠");
// {姓名=[李四, 王五], 性格=[温柔贤惠]}
System.out.println(linkedMultiValueMap);
LinkedList<Object> list = new LinkedList<>();
list.add("张三");
list.add("李四");
list.add("沈六");
linkedMultiValueMap.put("姓名", list);
// {姓名=[张三, 李四, 沈六], 性格=[温柔贤惠]} 注意这里替换掉过去完整的数据了
System.out.println(linkedMultiValueMap);
List<Object> names = linkedMultiValueMap.get("姓名");
// [张三, 李四, 沈六]
System.out.println(names);
Set<Object> keySet = linkedMultiValueMap.keySet();
// [姓名, 性格]
System.out.println(keySet);
LinkedMultiValueMap<Object, Object> multiValueMap = new LinkedMultiValueMap<>();
multiValueMap.add("色彩", "黄色");
multiValueMap.add("色彩", "灰色");
linkedMultiValueMap.addAll(multiValueMap);
// {姓名=[张三, 李四, 沈六], 性格=[温柔贤惠], 色彩=[黄色, 灰色]}
System.out.println(linkedMultiValueMap);
LinkedList<String> eLinkedList = new LinkedList<String>();
eLinkedList.add("男");
eLinkedList.add("女");
linkedMultiValueMap.addAll("性别", eLinkedList);
// {姓名=[张三, 李四, 沈六], 性格=[温柔贤惠], 色彩=[黄色, 灰色], 性别=[男, 女]}
System.out.println(linkedMultiValueMap);
linkedMultiValueMap.clear();
// {}
System.out.println(linkedMultiValueMap);
boolean mapEmpty = linkedMultiValueMap.isEmpty();
// true
System.out.println(mapEmpty);
Map<Object, Object> hashMap = new HashMap<>();
hashMap.put("功能", "扫地");
hashMap.put("午饭", "米粥");
linkedMultiValueMap.setAll(hashMap);
// {功能=[扫地], 午饭=[米粥]}
System.out.println(linkedMultiValueMap);
int size = linkedMultiValueMap.size();
// 2
System.out.println(size);
Map<Object, Object> singleValueMap = linkedMultiValueMap.toSingleValueMap();
// {功能=扫地, 午饭=米粥}
System.out.println(singleValueMap);
Set<Map.Entry<Object, List<Object>>> entrySet = linkedMultiValueMap.entrySet();
// [功能=[扫地], 午饭=[米粥]]
System.out.println(entrySet);
boolean key = linkedMultiValueMap.containsKey("气温");
// false
System.out.println(key);
boolean value = linkedMultiValueMap.containsValue("米粥");
// false
System.out.println(value);
boolean key1 = linkedMultiValueMap.containsKey("午饭");
// true
System.out.println(key1);
// {功能=[扫地], 午饭=[米粥]}
System.out.println(linkedMultiValueMap);
boolean containsValue = linkedMultiValueMap.containsValue(new HashMap<>().put("午饭", "米粥"));
// false
System.out.println(containsValue);
List<String> strings = new ArrayList<>();
strings.add("米粥");
boolean containsValue1 = linkedMultiValueMap.containsValue(strings);
// true
System.out.println(containsValue1);
linkedMultiValueMap.add("午饭", "咸菜");
// {功能=[扫地], 午饭=[米粥, 咸菜]}
System.out.println(linkedMultiValueMap);
Object first = linkedMultiValueMap.getFirst("午饭");
// 米粥
System.out.println(first);
linkedMultiValueMap.remove("午饭");
// {功能=[扫地]}
System.out.println(linkedMultiValueMap);
return "结果请看Console";
}
}