mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
优化支持一键多值的Map集合扩展,为其添加统一接口
This commit is contained in:
parent
ccb7b61b8c
commit
6c001e868b
@ -1,16 +1,13 @@
|
||||
package cn.hutool.core.map;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
@ -35,7 +32,9 @@ public class MapWrapper<K, V> implements Map<K, V>, Iterable<Map.Entry<K, V>>, S
|
||||
* 默认初始大小
|
||||
*/
|
||||
protected static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
|
||||
|
||||
/**
|
||||
* 原始集合
|
||||
*/
|
||||
private Map<K, V> raw;
|
||||
|
||||
/**
|
||||
@ -52,9 +51,11 @@ public class MapWrapper<K, V> implements Map<K, V>, Iterable<Map.Entry<K, V>>, S
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param raw 被包装的Map
|
||||
* @param raw 被包装的Map,不允许为{@code null}
|
||||
* @throws NullPointerException 当被包装的集合为{@code null}时抛出
|
||||
*/
|
||||
public MapWrapper(final Map<K, V> raw) {
|
||||
Assert.notNull(raw, "raw must not null");
|
||||
this.raw = raw;
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,29 @@
|
||||
package cn.hutool.core.map.multi;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Opt;
|
||||
import cn.hutool.core.map.MapWrapper;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 值作为集合的Map实现,通过调用putValue可以在相同key时加入多个值,多个值用集合表示
|
||||
* {@link MultiValueMap}的基本实现
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param <C> 集合类型
|
||||
* @author looly
|
||||
* @since 5.7.4
|
||||
* @see SetValueMap
|
||||
* @see ListValueMap
|
||||
*/
|
||||
public abstract class AbsCollValueMap<K, V, C extends Collection<V>> extends MapWrapper<K, C> {
|
||||
public abstract class AbsCollValueMap<K, V> extends MapWrapper<K, Collection<V>> implements MultiValueMap<K, V> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
@ -27,94 +34,132 @@ public abstract class AbsCollValueMap<K, V, C extends Collection<V>> extends Map
|
||||
// ------------------------------------------------------------------------- Constructor start
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* 使用{@code mapFactory}创建的集合构造一个多值映射Map集合
|
||||
*
|
||||
* @param mapFactory 生成集合的工厂方法
|
||||
*/
|
||||
public AbsCollValueMap() {
|
||||
this(DEFAULT_INITIAL_CAPACITY);
|
||||
protected AbsCollValueMap(Supplier<Map<K, Collection<V>>> mapFactory) {
|
||||
super(mapFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* 基于{@link HashMap}构造一个多值映射集合
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
* @param map 提供初始数据的集合
|
||||
*/
|
||||
public AbsCollValueMap(final int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR);
|
||||
protected AbsCollValueMap(Map<K, Collection<V>> map) {
|
||||
super(new HashMap<>(map));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param m Map
|
||||
* 基于{@link HashMap}构造一个多值映射集合
|
||||
*/
|
||||
public AbsCollValueMap(final Map<? extends K, C> m) {
|
||||
this(DEFAULT_LOAD_FACTOR, m);
|
||||
protected AbsCollValueMap() {
|
||||
super(new HashMap<>(16));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param loadFactor 加载因子
|
||||
* @param m Map
|
||||
*/
|
||||
public AbsCollValueMap(final float loadFactor, final Map<? extends K, C> m) {
|
||||
this(m.size(), loadFactor);
|
||||
this.putAll(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
* @param loadFactor 加载因子
|
||||
*/
|
||||
public AbsCollValueMap(final int initialCapacity, final float loadFactor) {
|
||||
super(new HashMap<>(initialCapacity, loadFactor));
|
||||
}
|
||||
// ------------------------------------------------------------------------- Constructor end
|
||||
|
||||
|
||||
/**
|
||||
* 放入所有value
|
||||
* 将集合中的全部元素对追加到指定键对应的值集合中,效果等同于:
|
||||
* <pre>{@code
|
||||
* coll.forEach(t -> map.putValue(key, t))
|
||||
* }</pre>
|
||||
*
|
||||
* @param m valueMap
|
||||
* @since 5.7.4
|
||||
* @param key 键
|
||||
* @param coll 待添加的值集合
|
||||
* @return 是否成功添加
|
||||
*/
|
||||
public void putAllValues(final Map<? extends K, ? extends Collection<V>> m) {
|
||||
if(null != m){
|
||||
m.forEach((key, valueColl) -> {
|
||||
if(null != valueColl){
|
||||
valueColl.forEach((value) -> putValue(key, value));
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public boolean putAllValues(K key, Collection<V> coll) {
|
||||
if (ObjUtil.isNull(coll)) {
|
||||
return false;
|
||||
}
|
||||
return super.computeIfAbsent(key, k -> createCollection())
|
||||
.addAll(coll);
|
||||
}
|
||||
|
||||
/**
|
||||
* 放入Value<br>
|
||||
* 如果键对应值列表有值,加入,否则创建一个新列表后加入
|
||||
* 向指定键对应的值集合追加值,效果等同于:
|
||||
* <pre>{@code
|
||||
* map.computeIfAbsent(key, k -> new Collection()).add(value)
|
||||
* }</pre>
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @return 是否成功添加
|
||||
*/
|
||||
public void putValue(final K key, final V value) {
|
||||
C collection = this.get(key);
|
||||
if (null == collection) {
|
||||
collection = createCollection();
|
||||
this.put(key, collection);
|
||||
}
|
||||
collection.add(value);
|
||||
@Override
|
||||
public boolean putValue(K key, V value) {
|
||||
return super.computeIfAbsent(key, k -> createCollection())
|
||||
.add(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值
|
||||
* 将值从指定键下的值集合中删除
|
||||
*
|
||||
* @param key 键
|
||||
* @param index 第几个值的索引,越界返回null
|
||||
* @return 值或null
|
||||
* @param value 值
|
||||
* @return 是否成功删除
|
||||
*/
|
||||
public V get(final K key, final int index) {
|
||||
final Collection<V> collection = get(key);
|
||||
return CollUtil.get(collection, index);
|
||||
@Override
|
||||
public boolean removeValue(K key, V value) {
|
||||
return Opt.ofNullable(super.get(key))
|
||||
.map(t -> t.remove(value))
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将一批值从指定键下的值集合中删除
|
||||
*
|
||||
* @param key 键
|
||||
* @param values 值
|
||||
* @return 是否成功删除
|
||||
*/
|
||||
@Override
|
||||
public boolean removeAllValues(K key, Collection<V> values) {
|
||||
if (CollUtil.isEmpty(values)) {
|
||||
return false;
|
||||
}
|
||||
Collection<V> coll = get(key);
|
||||
return ObjUtil.isNotNull(coll) && coll.removeAll(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件过滤所有值集合中的值,并以新值生成新的值集合,新集合中的值集合类型与当前实例的默认值集合类型保持一致
|
||||
*
|
||||
* @param filter 判断方法
|
||||
* @return 当前实例
|
||||
*/
|
||||
@Override
|
||||
public MultiValueMap<K, V> filterAllValues(BiPredicate<K, V> filter) {
|
||||
entrySet().forEach(e -> {
|
||||
K k = e.getKey();
|
||||
Collection<V> coll = e.getValue().stream()
|
||||
.filter(v -> filter.test(k, v))
|
||||
.collect(Collectors.toCollection(this::createCollection));
|
||||
e.setValue(coll);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件替换所有值集合中的值,并以新值生成新的值集合,新集合中的值集合类型与当前实例的默认值集合类型保持一致
|
||||
*
|
||||
* @param operate 替换方法
|
||||
* @return 当前实例
|
||||
*/
|
||||
@Override
|
||||
public MultiValueMap<K, V> replaceAllValues(BiFunction<K, V, V> operate) {
|
||||
entrySet().forEach(e -> {
|
||||
K k = e.getKey();
|
||||
Collection<V> coll = e.getValue().stream()
|
||||
.map(v -> operate.apply(k, v))
|
||||
.collect(Collectors.toCollection(this::createCollection));
|
||||
e.setValue(coll);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,5 +168,6 @@ public abstract class AbsCollValueMap<K, V, C extends Collection<V>> extends Map
|
||||
*
|
||||
* @return {@link Collection}
|
||||
*/
|
||||
protected abstract C createCollection();
|
||||
protected abstract Collection<V> createCollection();
|
||||
|
||||
}
|
||||
|
@ -6,97 +6,67 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 值作为集合的Map实现,通过调用putValue可以在相同key时加入多个值,多个值用集合表示<br>
|
||||
* 此类可以通过传入函数自定义集合类型的创建规则
|
||||
* <p>{@link MultiValueMap}的通用实现,可视为值为{@link Collection}集合的{@link Map}集合。<br>
|
||||
* 构建时指定一个工厂方法用于生成原始的{@link Map}集合,然后再指定一个工厂方法用于生成自定义类型的值集合。<br>
|
||||
* 当调用{@link MultiValueMap}中格式为“putXXX”的方法时,将会为key创建值集合,并将key相同的值追加到集合中
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @author looly
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public class CollectionValueMap<K, V> extends AbsCollValueMap<K, V, Collection<V>> {
|
||||
public class CollectionValueMap<K, V> extends AbsCollValueMap<K, V> {
|
||||
|
||||
private static final long serialVersionUID = 9012989578038102983L;
|
||||
|
||||
private final Func0<Collection<V>> collectionCreateFunc;
|
||||
private final Func0<Collection<V>> collFactory;
|
||||
|
||||
// ------------------------------------------------------------------------- Constructor start
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* 创建一个多值映射集合,基于{@code mapFactory}与{@code collFactory}实现
|
||||
*
|
||||
* @param mapFactory 生成集合的工厂方法
|
||||
* @param collFactory 生成值集合的工厂方法
|
||||
*/
|
||||
public CollectionValueMap(Supplier<Map<K, Collection<V>>> mapFactory, Func0<Collection<V>> collFactory) {
|
||||
super(mapFactory);
|
||||
this.collFactory = collFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个多值映射集合,默认基于{@link HashMap}与{@code collFactory}生成的集合实现
|
||||
*
|
||||
* @param collFactory 生成值集合的工厂方法
|
||||
*/
|
||||
public CollectionValueMap(Func0<Collection<V>> collFactory) {
|
||||
this.collFactory = collFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个多值映射集合,默认基于{@link HashMap}与{@link ArrayList}实现
|
||||
*/
|
||||
public CollectionValueMap() {
|
||||
this(DEFAULT_INITIAL_CAPACITY);
|
||||
this.collFactory = ArrayList::new;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* 创建一个多值映射集合,默认基于{@link HashMap}与{@link ArrayList}实现
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
* @param map 提供数据的原始集合
|
||||
*/
|
||||
public CollectionValueMap(final int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR);
|
||||
public CollectionValueMap(Map<K, Collection<V>> map) {
|
||||
super(map);
|
||||
this.collFactory = ArrayList::new;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param m Map
|
||||
*/
|
||||
public CollectionValueMap(final Map<? extends K, ? extends Collection<V>> m) {
|
||||
this(DEFAULT_LOAD_FACTOR, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param loadFactor 加载因子
|
||||
* @param m Map
|
||||
*/
|
||||
public CollectionValueMap(final float loadFactor, final Map<? extends K, ? extends Collection<V>> m) {
|
||||
this(loadFactor, m, ArrayList::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
* @param loadFactor 加载因子
|
||||
*/
|
||||
public CollectionValueMap(final int initialCapacity, final float loadFactor) {
|
||||
this(initialCapacity, loadFactor, ArrayList::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param loadFactor 加载因子
|
||||
* @param m Map
|
||||
* @param collectionCreateFunc Map中值的集合创建函数
|
||||
* @since 5.7.4
|
||||
*/
|
||||
public CollectionValueMap(final float loadFactor, final Map<? extends K, ? extends Collection<V>> m, final Func0<Collection<V>> collectionCreateFunc) {
|
||||
this(m.size(), loadFactor, collectionCreateFunc);
|
||||
this.putAll(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
* @param loadFactor 加载因子
|
||||
* @param collectionCreateFunc Map中值的集合创建函数
|
||||
* @since 5.7.4
|
||||
*/
|
||||
public CollectionValueMap(final int initialCapacity, final float loadFactor, final Func0<Collection<V>> collectionCreateFunc) {
|
||||
super(new HashMap<>(initialCapacity, loadFactor));
|
||||
this.collectionCreateFunc = collectionCreateFunc;
|
||||
}
|
||||
// ------------------------------------------------------------------------- Constructor end
|
||||
|
||||
@Override
|
||||
protected Collection<V> createCollection() {
|
||||
return collectionCreateFunc.callWithRuntimeException();
|
||||
return collFactory.callWithRuntimeException();
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
package cn.hutool.core.map.multi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 值作为集合List的Map实现,通过调用putValue可以在相同key时加入多个值,多个值用集合表示
|
||||
@ -15,55 +12,35 @@ import java.util.Map;
|
||||
* @param <V> 值类型
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public class ListValueMap<K, V> extends AbsCollValueMap<K, V, List<V>> {
|
||||
public class ListValueMap<K, V> extends AbsCollValueMap<K, V> {
|
||||
private static final long serialVersionUID = 6044017508487827899L;
|
||||
|
||||
// ------------------------------------------------------------------------- Constructor start
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* 基于{@code mapFactory}创建一个值为{@link List}的多值映射集合
|
||||
*
|
||||
* @param mapFactory 创建集合的工厂反方
|
||||
*/
|
||||
public ListValueMap(Supplier<Map<K, Collection<V>>> mapFactory) {
|
||||
super(mapFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于{@link HashMap}创建一个值为{@link List}的多值映射集合
|
||||
*
|
||||
* @param map 提供数据的原始集合
|
||||
*/
|
||||
public ListValueMap(Map<K, Collection<V>> map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于{@link HashMap}创建一个值为{@link List}的多值映射集合
|
||||
*/
|
||||
public ListValueMap() {
|
||||
this(DEFAULT_INITIAL_CAPACITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
*/
|
||||
public ListValueMap(final int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param m Map
|
||||
*/
|
||||
public ListValueMap(final Map<? extends K, ? extends Collection<V>> m) {
|
||||
this(DEFAULT_LOAD_FACTOR, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param loadFactor 加载因子
|
||||
* @param m Map
|
||||
*/
|
||||
public ListValueMap(final float loadFactor, final Map<? extends K, ? extends Collection<V>> m) {
|
||||
this(m.size(), loadFactor);
|
||||
this.putAllValues(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
* @param loadFactor 加载因子
|
||||
*/
|
||||
public ListValueMap(final int initialCapacity, final float loadFactor) {
|
||||
super(new HashMap<>(initialCapacity, loadFactor));
|
||||
}
|
||||
// ------------------------------------------------------------------------- Constructor end
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,250 @@
|
||||
package cn.hutool.core.map.multi;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>一个键对应多个值的集合{@link Map}实现,提供针对键对应的值集合中的元素而非值集合本身的一些快捷操作,
|
||||
* 本身可作为一个值为{@link Collection}类型的{@link Map}使用。<br>
|
||||
*
|
||||
* <h3>值集合类型</h3>
|
||||
* <p>值集合的类型由接口的实现类自行维护,当通过{@link MultiValueMap}定义的方法进行增删改操作时,
|
||||
* 实现类应保证通过通过实例方法获得的集合类型都一致。但是若用户直接通过{@link Map}定义的方法进行增删改操作时,
|
||||
* 实例无法保证通过实例方法获得的集合类型都一致。<br>
|
||||
* 因此,若无必要则更推荐通过{@link MultiValueMap}定义的方法进行操作。
|
||||
*
|
||||
* <h3>对值集合的修改</h3>
|
||||
* <p>当通过实例方法获得值集合时,若该集合允许修改,则对值集合的修改将会影响到其所属的{@link MultiValueMap}实例,反之亦然。
|
||||
* 因此当同时遍历当前实例或者值集合时,若存在写操作,则需要注意可能引发的{@link ConcurrentModificationException}。
|
||||
*
|
||||
* @author huangchengxing
|
||||
* @since 6.0.0
|
||||
* @see AbsCollValueMap
|
||||
* @see CollectionValueMap
|
||||
* @see ListValueMap
|
||||
* @see SetValueMap
|
||||
*/
|
||||
public interface MultiValueMap<K, V> extends Map<K, Collection<V>> {
|
||||
|
||||
// =================== override ===================
|
||||
|
||||
/**
|
||||
* 更新键对应的值集合 <br>
|
||||
* 注意:该操作将移除键对应的旧值集合,若仅需向值集合追加应值,则应使用{@link #putAllValues(Object, Collection)}
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 键对应的新值集合
|
||||
* @return 旧值集合
|
||||
*/
|
||||
@Override
|
||||
Collection<V> put(K key, Collection<V> value);
|
||||
|
||||
/**
|
||||
* 更新全部键的值集合 <br>
|
||||
* 注意:该操作将移除键对应的旧值集合,若仅需向值集合追加应值,则应使用{@link #putAllValues(Object, Collection)}
|
||||
*
|
||||
* @param map 需要更新的键值对集合
|
||||
*/
|
||||
@Override
|
||||
void putAll(Map<? extends K, ? extends Collection<V>> map);
|
||||
|
||||
// =================== write operate ===================
|
||||
|
||||
/**
|
||||
* 将集合中的全部键值对追加到当前实例中,效果等同于:
|
||||
* <pre>{@code
|
||||
* for (Entry<K, Collection<V>> entry : m.entrySet()) {
|
||||
* K key = entry.getKey();
|
||||
* Collection<V> coll = entry.getValues();
|
||||
* for (V val : coll) {
|
||||
* map.putValue(key, val)
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param m 待添加的集合
|
||||
*/
|
||||
default void putAllValues(final Map<? extends K, ? extends Collection<V>> m) {
|
||||
if (CollUtil.isNotEmpty(m)) {
|
||||
m.forEach(this::putAllValues);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将集合中的全部元素对追加到指定键对应的值集合中,效果等同于:
|
||||
* <pre>{@code
|
||||
* for (V val : coll) {
|
||||
* map.putValue(key, val)
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param key 键
|
||||
* @param coll 待添加的值集合
|
||||
* @return 是否成功添加
|
||||
*/
|
||||
boolean putAllValues(K key, final Collection<V> coll);
|
||||
|
||||
/**
|
||||
* 将数组中的全部元素追加到指定的值集合中,效果等同于:
|
||||
* <pre>{@code
|
||||
* for (V val : values) {
|
||||
* map.putValue(key, val)
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param key 键
|
||||
* @param values 待添加的值
|
||||
* @return boolean
|
||||
*/
|
||||
default boolean putValues(final K key, final V... values) {
|
||||
return ArrayUtil.isNotEmpty(values) && putAllValues(key, Arrays.asList(values));
|
||||
}
|
||||
|
||||
/**
|
||||
* 向指定键对应的值集合追加值,效果等同于:
|
||||
* <pre>{@code
|
||||
* Collection<V> coll = map.get(key);
|
||||
* if(null == coll) {
|
||||
* coll.add(value);
|
||||
* map.put(coll);
|
||||
* } else {
|
||||
* coll.add(value);
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @return 是否成功添加
|
||||
*/
|
||||
boolean putValue(final K key, final V value);
|
||||
|
||||
/**
|
||||
* 将值从指定键下的值集合中删除
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @return 是否成功删除
|
||||
*/
|
||||
boolean removeValue(final K key, final V value);
|
||||
|
||||
/**
|
||||
* 将一批值从指定键下的值集合中删除
|
||||
*
|
||||
* @param key 键
|
||||
* @param values 值数组
|
||||
* @return 是否成功删除
|
||||
*/
|
||||
default boolean removeValues(final K key, final V... values) {
|
||||
return ArrayUtil.isNotEmpty(values) && removeAllValues(key, Arrays.asList(values));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将一批值从指定键下的值集合中删除
|
||||
*
|
||||
* @param key 键
|
||||
* @param values 值集合
|
||||
* @return 是否成功删除
|
||||
*/
|
||||
boolean removeAllValues(final K key, final Collection<V> values);
|
||||
|
||||
/**
|
||||
* 根据条件过滤所有值集合中的值,并以新值生成新的值集合,新集合中的值集合类型与当前实例的默认值集合类型保持一致
|
||||
*
|
||||
* @param filter 判断方法
|
||||
* @return 当前实例
|
||||
*/
|
||||
default MultiValueMap<K, V> filterAllValues(Predicate<V> filter) {
|
||||
return filterAllValues((k, v) -> filter.test(v));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件过滤所有值集合中的值,并以新值生成新的值集合,新集合中的值集合类型与当前实例的默认值集合类型保持一致
|
||||
*
|
||||
* @param filter 判断方法
|
||||
* @return 当前实例
|
||||
*/
|
||||
MultiValueMap<K, V> filterAllValues(BiPredicate<K, V> filter);
|
||||
|
||||
/**
|
||||
* 根据条件替换所有值集合中的值,并以新值生成新的值集合,新集合中的值集合类型与当前实例的默认值集合类型保持一致
|
||||
*
|
||||
* @param operate 替换方法
|
||||
* @return 当前实例
|
||||
*/
|
||||
default MultiValueMap<K, V> replaceAllValues(UnaryOperator<V> operate) {
|
||||
return replaceAllValues((k, v) -> operate.apply(v));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件替换所有值集合中的值,并以新值生成新的值集合,新集合中的值集合类型与当前实例的默认值集合类型保持一致
|
||||
*
|
||||
* @param operate 替换方法
|
||||
* @return 当前实例
|
||||
*/
|
||||
MultiValueMap<K, V> replaceAllValues(BiFunction<K, V, V> operate);
|
||||
|
||||
// =================== read operate ===================
|
||||
|
||||
/**
|
||||
* 获取键对应的值,若值不存在,则返回{@link Collections#emptyList()}。效果等同于:
|
||||
* <pre>{@code
|
||||
* map.getOrDefault(key, Collections.emptyList())
|
||||
* }</pre>
|
||||
*
|
||||
* @param key 键
|
||||
* @return 值集合
|
||||
*/
|
||||
default Collection<V> getValues(final K key) {
|
||||
return getOrDefault(key, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取键对应值的数量,若键对应的值不存在,则返回{@code 0}
|
||||
*
|
||||
* @param key 键
|
||||
* @return 值的数量
|
||||
*/
|
||||
default int size(final K key) {
|
||||
return getValues(key).size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历所有键值对,效果等同于:
|
||||
* <pre>{@code
|
||||
* for (Entry<K, Collection<V>> entry : entrySet()) {
|
||||
* K key = entry.getKey();
|
||||
* Collection<V> coll = entry.getValues();
|
||||
* for (V val : coll) {
|
||||
* consumer.accept(key, val);
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param consumer 操作
|
||||
*/
|
||||
default void allForEach(BiConsumer<K, V> consumer) {
|
||||
forEach((k, coll) -> coll.forEach(v -> consumer.accept(k, v)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有的值,效果等同于:
|
||||
* <pre>{@code
|
||||
* List<V> results = new ArrayList<>();
|
||||
* for (Collection<V> coll : values()) {
|
||||
* results.addAll(coll);
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @return 值
|
||||
*/
|
||||
default Collection<V> allValues() {
|
||||
return values().stream()
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
package cn.hutool.core.map.multi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 值作为集合Set(LinkedHashSet)的Map实现,通过调用putValue可以在相同key时加入多个值,多个值用集合表示
|
||||
@ -15,59 +12,40 @@ import java.util.Set;
|
||||
* @param <V> 值类型
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public class SetValueMap<K, V> extends AbsCollValueMap<K, V, Set<V>> {
|
||||
public class SetValueMap<K, V> extends AbsCollValueMap<K, V> {
|
||||
private static final long serialVersionUID = 6044017508487827899L;
|
||||
|
||||
// ------------------------------------------------------------------------- Constructor start
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* 基于{@code mapFactory}创建一个值为{@link Set}的多值映射集合
|
||||
*
|
||||
* @param mapFactory 创建集合的工厂反方
|
||||
*/
|
||||
public SetValueMap(Supplier<Map<K, Collection<V>>> mapFactory) {
|
||||
super(mapFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于{@link HashMap}创建一个值为{@link Set}的多值映射集合
|
||||
*
|
||||
* @param map 提供数据的原始集合
|
||||
*/
|
||||
public SetValueMap(Map<K, Collection<V>> map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于{@link HashMap}创建一个值为{@link Set}的多值映射集合
|
||||
*/
|
||||
public SetValueMap() {
|
||||
this(DEFAULT_INITIAL_CAPACITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
*/
|
||||
public SetValueMap(final int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param m Map
|
||||
*/
|
||||
public SetValueMap(final Map<? extends K, ? extends Collection<V>> m) {
|
||||
this(DEFAULT_LOAD_FACTOR, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param loadFactor 加载因子
|
||||
* @param m Map
|
||||
*/
|
||||
public SetValueMap(final float loadFactor, final Map<? extends K, ? extends Collection<V>> m) {
|
||||
this(m.size(), loadFactor);
|
||||
this.putAllValues(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
* @param loadFactor 加载因子
|
||||
*/
|
||||
public SetValueMap(final int initialCapacity, final float loadFactor) {
|
||||
super(new HashMap<>(initialCapacity, loadFactor));
|
||||
}
|
||||
// ------------------------------------------------------------------------- Constructor end
|
||||
|
||||
@Override
|
||||
protected Set<V> createCollection() {
|
||||
return new LinkedHashSet<>(DEFAULT_COLLECTION_INITIAL_CAPACITY);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,11 +3,12 @@ package cn.hutool.core.net.multipart;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.map.multi.ListValueMap;
|
||||
import cn.hutool.core.map.multi.MultiValueMap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@ -20,9 +21,9 @@ import java.util.Set;
|
||||
public class MultipartFormData {
|
||||
|
||||
/** 请求参数 */
|
||||
private final ListValueMap<String, String> requestParameters = new ListValueMap<>();
|
||||
private final MultiValueMap<String, String> requestParameters = new ListValueMap<>();
|
||||
/** 请求文件 */
|
||||
private final ListValueMap<String, UploadFile> requestFiles = new ListValueMap<>();
|
||||
private final MultiValueMap<String, UploadFile> requestFiles = new ListValueMap<>();
|
||||
/** 上传选项 */
|
||||
private final UploadSetting setting;
|
||||
|
||||
@ -101,9 +102,9 @@ public class MultipartFormData {
|
||||
* @return null未找到,否则返回值
|
||||
*/
|
||||
public String getParam(final String paramName) {
|
||||
final List<String> values = getListParam(paramName);
|
||||
final Collection<String> values = getListParam(paramName);
|
||||
if (CollUtil.isNotEmpty(values)) {
|
||||
return values.get(0);
|
||||
return CollUtil.get(values, 0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -122,7 +123,7 @@ public class MultipartFormData {
|
||||
* @return 数组表单值
|
||||
*/
|
||||
public String[] getArrayParam(final String paramName) {
|
||||
final List<String> listParam = getListParam(paramName);
|
||||
final Collection<String> listParam = getListParam(paramName);
|
||||
if(null != listParam){
|
||||
return listParam.toArray(new String[0]);
|
||||
}
|
||||
@ -136,7 +137,7 @@ public class MultipartFormData {
|
||||
* @return 数组表单值
|
||||
* @since 5.3.0
|
||||
*/
|
||||
public List<String> getListParam(final String paramName) {
|
||||
public Collection<String> getListParam(final String paramName) {
|
||||
return requestParameters.get(paramName);
|
||||
}
|
||||
|
||||
@ -154,7 +155,7 @@ public class MultipartFormData {
|
||||
*
|
||||
* @return 所有属性的集合
|
||||
*/
|
||||
public ListValueMap<String, String> getParamListMap() {
|
||||
public MultiValueMap<String, String> getParamListMap() {
|
||||
return this.requestParameters;
|
||||
}
|
||||
|
||||
@ -181,7 +182,7 @@ public class MultipartFormData {
|
||||
* @return 上传的文件列表
|
||||
*/
|
||||
public UploadFile[] getFiles(final String paramName) {
|
||||
final List<UploadFile> fileList = getFileList(paramName);
|
||||
final Collection<UploadFile> fileList = getFileList(paramName);
|
||||
if(null != fileList){
|
||||
return fileList.toArray(new UploadFile[0]);
|
||||
}
|
||||
@ -196,7 +197,7 @@ public class MultipartFormData {
|
||||
* @return 上传的文件列表
|
||||
* @since 5.3.0
|
||||
*/
|
||||
public List<UploadFile> getFileList(final String paramName) {
|
||||
public Collection<UploadFile> getFileList(final String paramName) {
|
||||
return requestFiles.get(paramName);
|
||||
}
|
||||
|
||||
@ -223,7 +224,7 @@ public class MultipartFormData {
|
||||
*
|
||||
* @return 文件映射
|
||||
*/
|
||||
public ListValueMap<String, UploadFile> getFileListValueMap() {
|
||||
public MultiValueMap<String, UploadFile> getFileListValueMap() {
|
||||
return this.requestFiles;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,160 @@
|
||||
package cn.hutool.core.map;
|
||||
|
||||
import cn.hutool.core.map.multi.CollectionValueMap;
|
||||
import cn.hutool.core.map.multi.MultiValueMap;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
public void putTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
Assert.assertNull(map.put(1, Arrays.asList("a", "b")));
|
||||
Collection<String> collection = map.put(1, Arrays.asList("c", "d"));
|
||||
Assert.assertEquals(Arrays.asList("a", "b"), collection);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAllTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
Map<Integer, Collection<String>> source = new HashMap<>();
|
||||
source.put(1, Arrays.asList("a", "b", "c"));
|
||||
map.putAll(source);
|
||||
Assert.assertEquals(1, map.size());
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putValueTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
Assert.assertTrue(map.putValue(1, "a"));
|
||||
Assert.assertTrue(map.putValue(1, "b"));
|
||||
Assert.assertTrue(map.putValue(1, "c"));
|
||||
Assert.assertEquals(1, map.size());
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAllValueTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
Assert.assertTrue(map.putAllValues(1, Arrays.asList("a", "b", "c")));
|
||||
Assert.assertEquals(1, map.size());
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
|
||||
|
||||
Map<Integer, Collection<String>> source = new HashMap<>();
|
||||
Assert.assertTrue(map.putValue(1, "e"));
|
||||
Assert.assertTrue(map.putValue(1, "f"));
|
||||
map.putAllValues(source);
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c", "e", "f"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
Assert.assertTrue(map.putValues(1, "a", "b", "c"));
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterAllValues() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
Assert.assertTrue(map.putValues(1, "a", "b", "c"));
|
||||
Assert.assertTrue(map.putValues(2, "a", "b", "c"));
|
||||
|
||||
Assert.assertEquals(map, map.filterAllValues((k, v) -> StrUtil.equals(v, "a")));
|
||||
Assert.assertEquals(Collections.singletonList("a"), map.getValues(1));
|
||||
Assert.assertEquals(Collections.singletonList("a"), map.getValues(2));
|
||||
|
||||
Assert.assertEquals(map, map.filterAllValues(v -> !StrUtil.equals(v, "a")));
|
||||
Assert.assertEquals(Collections.emptyList(), map.getValues(1));
|
||||
Assert.assertEquals(Collections.emptyList(), map.getValues(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllValues() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
Assert.assertTrue(map.putValues(1, "a", "b", "c"));
|
||||
Assert.assertTrue(map.putValues(2, "a", "b", "c"));
|
||||
|
||||
Assert.assertEquals(map, map.replaceAllValues((k, v) -> v + "2"));
|
||||
Assert.assertEquals(Arrays.asList("a2", "b2", "c2"), map.getValues(1));
|
||||
Assert.assertEquals(Arrays.asList("a2", "b2", "c2"), map.getValues(2));
|
||||
|
||||
Assert.assertEquals(map, map.replaceAllValues(v -> v + "3"));
|
||||
Assert.assertEquals(Arrays.asList("a23", "b23", "c23"), map.getValues(1));
|
||||
Assert.assertEquals(Arrays.asList("a23", "b23", "c23"), map.getValues(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeValueTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertFalse(map.removeValue(1, "d"));
|
||||
Assert.assertTrue(map.removeValue(1, "c"));
|
||||
Assert.assertEquals(Arrays.asList("a", "b"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeAllValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertFalse(map.removeAllValues(1, Arrays.asList("e", "f")));
|
||||
Assert.assertTrue(map.removeAllValues(1, Arrays.asList("b", "c")));
|
||||
Assert.assertEquals(Collections.singletonList("a"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertFalse(map.removeValues(1, "e", "f"));
|
||||
Assert.assertTrue(map.removeValues(1, "b", "c"));
|
||||
Assert.assertEquals(Collections.singletonList("a"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertEquals(Collections.emptyList(), map.getValues(2));
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), map.getValues(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sizeTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertEquals(0, map.size(2));
|
||||
Assert.assertEquals(3, map.size(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allForEachTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
List<Integer> keys = new ArrayList<>();
|
||||
List<String> values = new ArrayList<>();
|
||||
map.allForEach((k, v) -> {
|
||||
keys.add(k);
|
||||
values.add(v);
|
||||
});
|
||||
Assert.assertEquals(Arrays.asList(1, 1, 1), keys);
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), values);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>(new LinkedHashMap<>());
|
||||
map.putAllValues(1, Arrays.asList("a", "b", "c"));
|
||||
map.putAllValues(2, Arrays.asList("d", "e"));
|
||||
Assert.assertEquals(
|
||||
Arrays.asList("a", "b", "c", "d", "e"),
|
||||
map.allValues()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
package cn.hutool.core.map;
|
||||
|
||||
import cn.hutool.core.map.multi.ListValueMap;
|
||||
import cn.hutool.core.map.multi.MultiValueMap;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
public void putTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
Assert.assertNull(map.put(1, Arrays.asList("a", "b")));
|
||||
Collection<String> collection = map.put(1, Arrays.asList("c", "d"));
|
||||
Assert.assertEquals(Arrays.asList("a", "b"), collection);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAllTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
Map<Integer, Collection<String>> source = new HashMap<>();
|
||||
source.put(1, Arrays.asList("a", "b", "c"));
|
||||
map.putAll(source);
|
||||
Assert.assertEquals(1, map.size());
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putValueTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
Assert.assertTrue(map.putValue(1, "a"));
|
||||
Assert.assertTrue(map.putValue(1, "b"));
|
||||
Assert.assertTrue(map.putValue(1, "c"));
|
||||
Assert.assertEquals(1, map.size());
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAllValueTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
Assert.assertTrue(map.putAllValues(1, Arrays.asList("a", "b", "c")));
|
||||
Assert.assertEquals(1, map.size());
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
|
||||
|
||||
Map<Integer, Collection<String>> source = new HashMap<>();
|
||||
Assert.assertTrue(map.putValue(1, "e"));
|
||||
Assert.assertTrue(map.putValue(1, "f"));
|
||||
map.putAllValues(source);
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c", "e", "f"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
Assert.assertTrue(map.putValues(1, "a", "b", "c"));
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeValueTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertFalse(map.removeValue(1, "d"));
|
||||
Assert.assertTrue(map.removeValue(1, "c"));
|
||||
Assert.assertEquals(Arrays.asList("a", "b"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeAllValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertFalse(map.removeAllValues(1, Arrays.asList("e", "f")));
|
||||
Assert.assertTrue(map.removeAllValues(1, Arrays.asList("b", "c")));
|
||||
Assert.assertEquals(Collections.singletonList("a"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertFalse(map.removeValues(1, "e", "f"));
|
||||
Assert.assertTrue(map.removeValues(1, "b", "c"));
|
||||
Assert.assertEquals(Collections.singletonList("a"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterAllValues() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
Assert.assertTrue(map.putValues(1, "a", "b", "c"));
|
||||
Assert.assertTrue(map.putValues(2, "a", "b", "c"));
|
||||
|
||||
Assert.assertEquals(map, map.filterAllValues((k, v) -> StrUtil.equals(v, "a")));
|
||||
Assert.assertEquals(Collections.singletonList("a"), map.getValues(1));
|
||||
Assert.assertEquals(Collections.singletonList("a"), map.getValues(2));
|
||||
|
||||
Assert.assertEquals(map, map.filterAllValues(v -> !StrUtil.equals(v, "a")));
|
||||
Assert.assertEquals(Collections.emptyList(), map.getValues(1));
|
||||
Assert.assertEquals(Collections.emptyList(), map.getValues(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllValues() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
Assert.assertTrue(map.putValues(1, "a", "b", "c"));
|
||||
Assert.assertTrue(map.putValues(2, "a", "b", "c"));
|
||||
|
||||
Assert.assertEquals(map, map.replaceAllValues((k, v) -> v + "2"));
|
||||
Assert.assertEquals(Arrays.asList("a2", "b2", "c2"), map.getValues(1));
|
||||
Assert.assertEquals(Arrays.asList("a2", "b2", "c2"), map.getValues(2));
|
||||
|
||||
Assert.assertEquals(map, map.replaceAllValues(v -> v + "3"));
|
||||
Assert.assertEquals(Arrays.asList("a23", "b23", "c23"), map.getValues(1));
|
||||
Assert.assertEquals(Arrays.asList("a23", "b23", "c23"), map.getValues(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertEquals(Collections.emptyList(), map.getValues(2));
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), map.getValues(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sizeTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertEquals(0, map.size(2));
|
||||
Assert.assertEquals(3, map.size(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allForEachTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
List<Integer> keys = new ArrayList<>();
|
||||
List<String> values = new ArrayList<>();
|
||||
map.allForEach((k, v) -> {
|
||||
keys.add(k);
|
||||
values.add(v);
|
||||
});
|
||||
Assert.assertEquals(Arrays.asList(1, 1, 1), keys);
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), values);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putAllValues(1, Arrays.asList("a", "b", "c"));
|
||||
map.putAllValues(2, Arrays.asList("d", "e"));
|
||||
Assert.assertEquals(
|
||||
Arrays.asList("a", "b", "c", "d", "e"),
|
||||
map.allValues()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
package cn.hutool.core.map;
|
||||
|
||||
import cn.hutool.core.map.multi.MultiValueMap;
|
||||
import cn.hutool.core.map.multi.SetValueMap;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
public void putTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
Assert.assertNull(map.put(1, Arrays.asList("a", "b")));
|
||||
Collection<String> collection = map.put(1, Arrays.asList("c", "d"));
|
||||
Assert.assertEquals(Arrays.asList("a", "b"), collection);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAllTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
Map<Integer, Collection<String>> source = new HashMap<>();
|
||||
source.put(1, Arrays.asList("a", "b", "c"));
|
||||
map.putAll(source);
|
||||
Assert.assertEquals(1, map.size());
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putValueTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
Assert.assertTrue(map.putValue(1, "a"));
|
||||
Assert.assertTrue(map.putValue(1, "b"));
|
||||
Assert.assertTrue(map.putValue(1, "c"));
|
||||
Assert.assertEquals(1, map.size());
|
||||
Assert.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c")), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAllValueTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
Assert.assertTrue(map.putAllValues(1, Arrays.asList("a", "b", "c")));
|
||||
Assert.assertEquals(1, map.size());
|
||||
Assert.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c")), map.get(1));
|
||||
|
||||
Map<Integer, Collection<String>> source = new HashMap<>();
|
||||
Assert.assertTrue(map.putValue(1, "e"));
|
||||
Assert.assertFalse(map.putValue(1, "e"));
|
||||
Assert.assertTrue(map.putValue(1, "f"));
|
||||
Assert.assertFalse(map.putValue(1, "f"));
|
||||
map.putAllValues(source);
|
||||
Assert.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c", "e", "f")), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
Assert.assertTrue(map.putValues(1, "a", "b", "c"));
|
||||
Assert.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c")), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeValueTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertFalse(map.removeValue(1, "d"));
|
||||
Assert.assertTrue(map.removeValue(1, "c"));
|
||||
Assert.assertEquals(new HashSet<>(Arrays.asList("a", "b")), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeAllValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertFalse(map.removeAllValues(1, Arrays.asList("e", "f")));
|
||||
Assert.assertTrue(map.removeAllValues(1, Arrays.asList("b", "c")));
|
||||
Assert.assertEquals(Collections.singleton("a"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertFalse(map.removeValues(1, "e", "f"));
|
||||
Assert.assertTrue(map.removeValues(1, "b", "c"));
|
||||
Assert.assertEquals(Collections.singleton("a"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterAllValues() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
Assert.assertTrue(map.putValues(1, "a", "b", "c"));
|
||||
Assert.assertTrue(map.putValues(2, "a", "b", "c"));
|
||||
|
||||
Assert.assertEquals(map, map.filterAllValues((k, v) -> StrUtil.equals(v, "a")));
|
||||
Assert.assertEquals(Collections.singleton("a"), map.getValues(1));
|
||||
Assert.assertEquals(Collections.singleton("a"), map.getValues(2));
|
||||
|
||||
Assert.assertEquals(map, map.filterAllValues(v -> !StrUtil.equals(v, "a")));
|
||||
Assert.assertEquals(Collections.emptySet(), map.getValues(1));
|
||||
Assert.assertEquals(Collections.emptySet(), map.getValues(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllValues() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
Assert.assertTrue(map.putValues(1, "a", "b", "c"));
|
||||
Assert.assertTrue(map.putValues(2, "a", "b", "c"));
|
||||
|
||||
Assert.assertEquals(map, map.replaceAllValues((k, v) -> v + "2"));
|
||||
Assert.assertEquals(new HashSet<>(Arrays.asList("a2", "b2", "c2")), map.getValues(1));
|
||||
Assert.assertEquals(new HashSet<>(Arrays.asList("a2", "b2", "c2")), map.getValues(2));
|
||||
|
||||
Assert.assertEquals(map, map.replaceAllValues(v -> v + "3"));
|
||||
Assert.assertEquals(new HashSet<>(Arrays.asList("a23", "b23", "c23")), map.getValues(1));
|
||||
Assert.assertEquals(new HashSet<>(Arrays.asList("a23", "b23", "c23")), map.getValues(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertEquals(Collections.emptyList(), map.getValues(2));
|
||||
Assert.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c")), map.getValues(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sizeTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assert.assertEquals(0, map.size(2));
|
||||
Assert.assertEquals(3, map.size(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allForEachTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
List<Integer> keys = new ArrayList<>();
|
||||
List<String> values = new ArrayList<>();
|
||||
map.allForEach((k, v) -> {
|
||||
keys.add(k);
|
||||
values.add(v);
|
||||
});
|
||||
Assert.assertEquals(Arrays.asList(1, 1, 1), keys);
|
||||
Assert.assertEquals(Arrays.asList("a", "b", "c"), values);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putAllValues(1, Arrays.asList("a", "b", "c"));
|
||||
map.putAllValues(2, Arrays.asList("d", "e"));
|
||||
Assert.assertEquals(
|
||||
Arrays.asList("a", "b", "c", "d", "e"),
|
||||
map.allValues()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user