JDK没有提供MultiValueMap, Spring提供的MultiValueMap既不支持多线程,也把集合类型写死成List了。所以,就自己写了一个。希望对你有用!
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import cn.hutool.core.map.MapUtil;
public interface MultiValueMap<K, V, C extends Collection<V>> extends Map<K, C> {
default boolean add(K k, V v) {
return MapUtil.computeIfAbsent(this, k, this::mapping).add(v);
}
default boolean addAll(K k, Collection<V> collection) {
return MapUtil.computeIfAbsent(this, k, this::mapping).addAll(collection);
}
default boolean contains(K k, V v) {
return containsKey(k) && get(k).contains(v);
}
default List<V> allValues() {
return values().stream().flatMap(Collection::stream).collect(Collectors.toList());
}
default <R> List<R> map(BiFunction<K, V, R> biFunction) {
return entrySet().stream()
.flatMap(entry -> entry.getValue().stream().map(value -> biFunction.apply(entry.getKey(), value)))
.collect(Collectors.toList());
}
C mapping(K k);
static <K, V> SetValueMap<K, V> setValueMap() {
return new SetValueMap<>();
}
static <K, V> ListValueMap<K, V> listValueMap() {
return new ListValueMap<>();
}
static <K, V> ConcurrentSetValueMap<K, V> concurrentSetValueMap() {
return new ConcurrentSetValueMap<>();
}
static <K, V> ConcurrentListValueMap<K, V> concurrentListValueMap() {
return new ConcurrentListValueMap<>();
}
}
import java.util.AbstractMap;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
public class MultiValueMapImpl<K, V, C extends Collection<V>> extends AbstractMap<K, C>
implements MultiValueMap<K, V, C> {
private final Map<K, C> map;
private final Function<K, C> function;
public MultiValueMapImpl(Map<K, C> map, Function<K, C> function) {
this.map = map;
this.function = function;
}
@Override
public C mapping(K k) {
return function.apply(k);
}
@Override
public Set<Entry<K, C>> entrySet() {
return map.entrySet();
}
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ListValueMap<K, V> extends HashMap<K, List<V>> implements MultiValueMap<K, V, List<V>> {
public ListValueMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
public ListValueMap(int initialCapacity) {
super(initialCapacity);
}
public ListValueMap() {
}
public ListValueMap(Map<? extends K, ? extends List<V>> m) {
super(m);
}
@Override
public List<V> mapping(K k) {
return new ArrayList<>();
}
}
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class SetValueMap<K, V> extends HashMap<K, Set<V>> implements MultiValueMap<K, V, Set<V>> {
public SetValueMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
public SetValueMap(int initialCapacity) {
super(initialCapacity);
}
public SetValueMap() {
}
public SetValueMap(Map<? extends K, ? extends Set<V>> m) {
super(m);
}
@Override
public Set<V> mapping(K k) {
return new HashSet<>();
}
}
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
public class ConcurrentListValueMap<K, V> extends ConcurrentHashMap<K, List<V>> implements MultiValueMap<K, V, List<V>> {
public ConcurrentListValueMap() {
}
public ConcurrentListValueMap(int initialCapacity) {
super(initialCapacity);
}
public ConcurrentListValueMap(Map<? extends K, ? extends List<V>> m) {
super(m);
}
public ConcurrentListValueMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
public ConcurrentListValueMap(int initialCapacity, float loadFactor, int concurrencyLevel) {
super(initialCapacity, loadFactor, concurrencyLevel);
}
@Override
public List<V> mapping(K k) {
return new CopyOnWriteArrayList<>();
}
}
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
public class ConcurrentSetValueMap<K, V> extends ConcurrentHashMap<K, Set<V>> implements MultiValueMap<K, V, Set<V>> {
public ConcurrentSetValueMap() {
}
public ConcurrentSetValueMap(int initialCapacity) {
super(initialCapacity);
}
public ConcurrentSetValueMap(Map<? extends K, ? extends Set<V>> m) {
super(m);
}
public ConcurrentSetValueMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
public ConcurrentSetValueMap(int initialCapacity, float loadFactor, int concurrencyLevel) {
super(initialCapacity, loadFactor, concurrencyLevel);
}
@Override
public Set<V> mapping(K k) {
return new CopyOnWriteArraySet<>();
}
}