mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
Merge remote-tracking branch 'gitee/v6-dev' into feat-stream-ext
This commit is contained in:
commit
43bd15b515
@ -42,11 +42,14 @@ import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Month;
|
||||
import java.time.MonthDay;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.Period;
|
||||
@ -201,6 +204,10 @@ public class RegisterConverter implements Converter, Serializable {
|
||||
defaultConverterMap.put(ZonedDateTime.class, TemporalAccessorConverter.INSTANCE);
|
||||
defaultConverterMap.put(OffsetDateTime.class, TemporalAccessorConverter.INSTANCE);
|
||||
defaultConverterMap.put(OffsetTime.class, TemporalAccessorConverter.INSTANCE);
|
||||
defaultConverterMap.put(DayOfWeek.class, TemporalAccessorConverter.INSTANCE);
|
||||
defaultConverterMap.put(Month.class, TemporalAccessorConverter.INSTANCE);
|
||||
defaultConverterMap.put(MonthDay.class, TemporalAccessorConverter.INSTANCE);
|
||||
|
||||
defaultConverterMap.put(Period.class, new PeriodConverter());
|
||||
defaultConverterMap.put(Duration.class, new DurationConverter());
|
||||
|
||||
|
@ -12,10 +12,13 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Month;
|
||||
import java.time.MonthDay;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.chrono.Era;
|
||||
import java.time.chrono.IsoEra;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Calendar;
|
||||
@ -113,6 +116,16 @@ public class TemporalAccessorConverter extends AbstractConverter {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(DayOfWeek.class == targetClass){
|
||||
return DayOfWeek.valueOf(StrUtil.toString(value));
|
||||
} else if(Month.class == targetClass){
|
||||
return Month.valueOf(StrUtil.toString(value));
|
||||
} else if(Era.class == targetClass){
|
||||
return IsoEra.valueOf(StrUtil.toString(value));
|
||||
} else if(MonthDay.class == targetClass){
|
||||
return MonthDay.parse(value);
|
||||
}
|
||||
|
||||
final Instant instant;
|
||||
final ZoneId zoneId;
|
||||
if (null != this.format) {
|
||||
@ -139,6 +152,8 @@ public class TemporalAccessorConverter extends AbstractConverter {
|
||||
return Month.of(Math.toIntExact(time));
|
||||
} else if(targetClass == DayOfWeek.class){
|
||||
return DayOfWeek.of(Math.toIntExact(time));
|
||||
} else if(Era.class == targetClass){
|
||||
return IsoEra.of(Math.toIntExact(time));
|
||||
}
|
||||
|
||||
return parseFromInstant(targetClass, Instant.ofEpochMilli(time), null);
|
||||
@ -151,6 +166,14 @@ public class TemporalAccessorConverter extends AbstractConverter {
|
||||
* @return java.time中的对象
|
||||
*/
|
||||
private TemporalAccessor parseFromTemporalAccessor(final Class<?> targetClass, final TemporalAccessor temporalAccessor) {
|
||||
if(DayOfWeek.class == targetClass){
|
||||
return DayOfWeek.from(temporalAccessor);
|
||||
} else if(Month.class == targetClass){
|
||||
return Month.from(temporalAccessor);
|
||||
} else if(MonthDay.class == targetClass){
|
||||
return MonthDay.from(temporalAccessor);
|
||||
}
|
||||
|
||||
TemporalAccessor result = null;
|
||||
if (temporalAccessor instanceof LocalDateTime) {
|
||||
result = parseFromLocalDateTime(targetClass, (LocalDateTime) temporalAccessor);
|
||||
|
@ -3,15 +3,18 @@ package cn.hutool.core.date;
|
||||
import cn.hutool.core.date.format.GlobalCustomFormat;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Month;
|
||||
import java.time.MonthDay;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.chrono.Era;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalField;
|
||||
@ -94,7 +97,7 @@ public class TemporalAccessorUtil extends TemporalUtil{
|
||||
return null;
|
||||
}
|
||||
|
||||
if(time instanceof Month){
|
||||
if(time instanceof DayOfWeek || time instanceof java.time.Month || time instanceof Era || time instanceof MonthDay){
|
||||
return time.toString();
|
||||
}
|
||||
|
||||
@ -111,7 +114,9 @@ public class TemporalAccessorUtil extends TemporalUtil{
|
||||
|
||||
/**
|
||||
* {@link TemporalAccessor}转换为 时间戳(从1970-01-01T00:00:00Z开始的毫秒数)<br>
|
||||
* 如果为{@link Month},调用{@link Month#getValue()}
|
||||
* 如果为{@link Month},调用{@link Month#getValue()}<br>
|
||||
* 如果为{@link DayOfWeek},调用{@link DayOfWeek#getValue()}<br>
|
||||
* 如果为{@link Era},调用{@link Era#getValue()}
|
||||
*
|
||||
* @param temporalAccessor Date对象
|
||||
* @return {@link Instant}对象
|
||||
@ -120,6 +125,10 @@ public class TemporalAccessorUtil extends TemporalUtil{
|
||||
public static long toEpochMilli(final TemporalAccessor temporalAccessor) {
|
||||
if(temporalAccessor instanceof Month){
|
||||
return ((Month) temporalAccessor).getValue();
|
||||
} else if(temporalAccessor instanceof DayOfWeek){
|
||||
return ((DayOfWeek) temporalAccessor).getValue();
|
||||
} else if(temporalAccessor instanceof Era){
|
||||
return ((Era) temporalAccessor).getValue();
|
||||
}
|
||||
return toInstant(temporalAccessor).toEpochMilli();
|
||||
}
|
||||
|
@ -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,30 @@
|
||||
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 CollectionValueMap
|
||||
* @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 +35,131 @@ 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,266 @@
|
||||
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>
|
||||
*
|
||||
* <p>值集合类型</p>
|
||||
* <p>值集合的类型由接口的实现类自行维护,当通过{@link MultiValueMap}定义的方法进行增删改操作时,
|
||||
* 实现类应保证通过通过实例方法获得的集合类型都一致。但是若用户直接通过{@link Map}定义的方法进行增删改操作时,
|
||||
* 实例无法保证通过实例方法获得的集合类型都一致。<br>
|
||||
* 因此,若无必要则更推荐通过{@link MultiValueMap}定义的方法进行操作。
|
||||
*
|
||||
* <p>对值集合的修改</p>
|
||||
* <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 旧值集合
|
||||
*/
|
||||
@SuppressWarnings("AbstractMethodOverridesAbstractMethod")
|
||||
@Override
|
||||
Collection<V> put(K key, Collection<V> value);
|
||||
|
||||
/**
|
||||
* 更新全部键的值集合 <br>
|
||||
* 注意:该操作将移除键对应的旧值集合,若仅需向值集合追加应值,则应使用{@link #putAllValues(Object, Collection)}
|
||||
*
|
||||
* @param map 需要更新的键值对集合
|
||||
*/
|
||||
@SuppressWarnings("AbstractMethodOverridesAbstractMethod")
|
||||
@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
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
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 是否成功删除
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
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 ===================
|
||||
|
||||
/**
|
||||
* 获取指定序号的值,若值不存在,返回{@code null}
|
||||
*
|
||||
* @param key 键
|
||||
* @param index 第几个值的索引,越界返回null
|
||||
* @return 值或null
|
||||
*/
|
||||
default V getValue(K key, int index) {
|
||||
final Collection<V> collection = get(key);
|
||||
return CollUtil.get(collection, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取键对应的值,若值不存在,则返回{@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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,24 @@
|
||||
/**
|
||||
* 多参数类型的Map实现,包括集合类型值的Map和Table
|
||||
* 多参数类型的Map实现,包括集合类型值的MultiValueMap和Table<br>
|
||||
* <ul>
|
||||
* <li>MultiValueMap:一个键对应多个值的集合的实现,类似于树的结构。</li>
|
||||
* <li>Table:使用两个键映射到一个值,类似于表格结构。</li>
|
||||
* </ul>
|
||||
*
|
||||
* <pre>
|
||||
* MultiValueMap
|
||||
* |
|
||||
* AbsCollValueMap
|
||||
* ||
|
||||
* [CollectionValueMap, SetValueMap, ListValueMap]
|
||||
* </pre>
|
||||
* <pre>
|
||||
* Table
|
||||
* |
|
||||
* AbsTable
|
||||
* ||
|
||||
* [RowKeyTable]
|
||||
* </pre>
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -301,6 +301,7 @@ public class ObjUtil {
|
||||
/**
|
||||
* 如果给定对象为{@code null} 返回默认值, 如果不为null 返回自定义handle处理后的返回值
|
||||
*
|
||||
* @param <R> 返回值类型
|
||||
* @param <T> 被检查对象类型
|
||||
* @param source Object 类型对象
|
||||
* @param handler 非空时自定义的处理方法
|
||||
@ -308,13 +309,29 @@ public class ObjUtil {
|
||||
* @return 处理后的返回值
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static <T> T defaultIfNull(final Object source, final Function<Object, T> handler, final Supplier<? extends T> defaultSupplier) {
|
||||
public static <T, R> R defaultIfNull(final T source, final Function<? super T, ? extends R> handler, final Supplier<? extends R> defaultSupplier) {
|
||||
if (isNotNull(source)) {
|
||||
return handler.apply(source);
|
||||
}
|
||||
return defaultSupplier.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果给定对象为{@code null}返回默认值, 如果不为null返回自定义handle处理后的返回值
|
||||
*
|
||||
* @param <R> 返回值类型
|
||||
* @param <T> 被检查对象类型
|
||||
* @param source Object 类型对象
|
||||
* @param handler 非空时自定义的处理方法
|
||||
* @param defaultValue 默认为空的返回值
|
||||
* @return 处理后的返回值
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static <T, R> R defaultIfNull(
|
||||
final T source, final Function<? super T, ? extends R> handler, final R defaultValue) {
|
||||
return isNull(source) ? defaultValue : handler.apply(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* 克隆对象<br>
|
||||
* 如果对象实现Cloneable接口,调用其clone方法<br>
|
||||
|
@ -1,29 +0,0 @@
|
||||
package cn.hutool.core.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 用于单元测试的注解类<br>
|
||||
* 注解类相关说明见:<a href="https://www.cnblogs.com/xdp-gacl/p/3622275.html">https://www.cnblogs.com/xdp-gacl/p/3622275.html</a>
|
||||
*
|
||||
* @author looly
|
||||
*/
|
||||
// Retention注解决定MyAnnotation注解的生命周期
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
// Target注解决定MyAnnotation注解可以加在哪些成分上,如加在类身上,或者属性身上,或者方法身上等成分
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
public @interface AnnotationForTest {
|
||||
|
||||
/**
|
||||
* 注解的默认属性值
|
||||
*
|
||||
* @return 属性值
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
@Alias("value")
|
||||
String retry() default "";
|
||||
}
|
@ -1,49 +1,136 @@
|
||||
package cn.hutool.core.annotation;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* test for {@link AnnotationUtil}
|
||||
*/
|
||||
public class AnnotationUtilTest {
|
||||
|
||||
@Test
|
||||
public void getCombinationAnnotationsTest(){
|
||||
final Annotation[] annotations = AnnotationUtil.getAnnotations(ClassWithAnnotation.class, true);
|
||||
Assert.assertNotNull(annotations);
|
||||
public void testToCombination() {
|
||||
final CombinationAnnotationElement element = AnnotationUtil.toCombination(ClassForTest.class);
|
||||
Assert.assertEquals(2, element.getAnnotations().length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnnotations() {
|
||||
Annotation[] annotations = AnnotationUtil.getAnnotations(ClassForTest.class, true);
|
||||
Assert.assertEquals(2, annotations.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCombinationAnnotationsWithClassTest(){
|
||||
final AnnotationForTest[] annotations = AnnotationUtil.getCombinationAnnotations(ClassWithAnnotation.class, AnnotationForTest.class);
|
||||
Assert.assertNotNull(annotations);
|
||||
annotations = AnnotationUtil.getAnnotations(ClassForTest.class, false);
|
||||
Assert.assertEquals(1, annotations.length);
|
||||
Assert.assertEquals("测试", annotations[0].value());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnotationValueTest() {
|
||||
final Object value = AnnotationUtil.getAnnotationValue(ClassWithAnnotation.class, AnnotationForTest.class);
|
||||
Assert.assertEquals("测试", value);
|
||||
|
||||
public void testGetCombinationAnnotations() {
|
||||
final MetaAnnotationForTest[] annotations = AnnotationUtil.getCombinationAnnotations(ClassForTest.class, MetaAnnotationForTest.class);
|
||||
Assert.assertEquals(1, annotations.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnotationSyncAlias() {
|
||||
// 直接获取
|
||||
Assert.assertEquals("", ClassWithAnnotation.class.getAnnotation(AnnotationForTest.class).retry());
|
||||
public void testAnnotations() {
|
||||
MetaAnnotationForTest[] annotations1 = AnnotationUtil.getAnnotations(ClassForTest.class, false, MetaAnnotationForTest.class);
|
||||
Assert.assertEquals(0, annotations1.length);
|
||||
annotations1 = AnnotationUtil.getAnnotations(ClassForTest.class, true, MetaAnnotationForTest.class);
|
||||
Assert.assertEquals(1, annotations1.length);
|
||||
|
||||
// 加别名适配
|
||||
final AnnotationForTest annotation = AnnotationUtil.getAnnotationAlias(ClassWithAnnotation.class, AnnotationForTest.class);
|
||||
Assert.assertEquals("测试", annotation.retry());
|
||||
Annotation[] annotations2 = AnnotationUtil.getAnnotations(
|
||||
ClassForTest.class, false, t -> ObjUtil.equals(t.annotationType(), MetaAnnotationForTest.class)
|
||||
);
|
||||
Assert.assertEquals(0, annotations2.length);
|
||||
annotations2 = AnnotationUtil.getAnnotations(
|
||||
ClassForTest.class, true, t -> ObjUtil.equals(t.annotationType(), MetaAnnotationForTest.class)
|
||||
);
|
||||
Assert.assertEquals(1, annotations2.length);
|
||||
}
|
||||
|
||||
@AnnotationForTest("测试")
|
||||
@RepeatAnnotationForTest
|
||||
static class ClassWithAnnotation{
|
||||
public void test(){
|
||||
|
||||
}
|
||||
@Test
|
||||
public void testGetAnnotation() {
|
||||
final MetaAnnotationForTest annotation = AnnotationUtil.getAnnotation(ClassForTest.class, MetaAnnotationForTest.class);
|
||||
Assert.assertNotNull(annotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasAnnotation() {
|
||||
Assert.assertTrue(AnnotationUtil.hasAnnotation(ClassForTest.class, MetaAnnotationForTest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnnotationValue() {
|
||||
final AnnotationForTest annotation = ClassForTest.class.getAnnotation(AnnotationForTest.class);
|
||||
Assert.assertEquals(annotation.value(), AnnotationUtil.getAnnotationValue(ClassForTest.class, AnnotationForTest.class));
|
||||
Assert.assertEquals(annotation.value(), AnnotationUtil.getAnnotationValue(ClassForTest.class, AnnotationForTest.class, "value"));
|
||||
Assert.assertNull(AnnotationUtil.getAnnotationValue(ClassForTest.class, AnnotationForTest.class, "property"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnnotationValueMap() {
|
||||
final AnnotationForTest annotation = ClassForTest.class.getAnnotation(AnnotationForTest.class);
|
||||
final Map<String, Object> valueMap = AnnotationUtil.getAnnotationValueMap(ClassForTest.class, AnnotationForTest.class);
|
||||
Assert.assertNotNull(valueMap);
|
||||
Assert.assertEquals(1, valueMap.size());
|
||||
Assert.assertEquals(annotation.value(), valueMap.get("value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRetentionPolicy() {
|
||||
final RetentionPolicy policy = AnnotationForTest.class.getAnnotation(Retention.class).value();
|
||||
Assert.assertEquals(policy, AnnotationUtil.getRetentionPolicy(AnnotationForTest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTargetType() {
|
||||
final ElementType[] types = AnnotationForTest.class.getAnnotation(Target.class).value();
|
||||
Assert.assertArrayEquals(types, AnnotationUtil.getTargetType(AnnotationForTest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsDocumented() {
|
||||
Assert.assertFalse(AnnotationUtil.isDocumented(AnnotationForTest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsInherited() {
|
||||
Assert.assertFalse(AnnotationUtil.isInherited(AnnotationForTest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetValue() {
|
||||
final AnnotationForTest annotation = ClassForTest.class.getAnnotation(AnnotationForTest.class);
|
||||
final String newValue = "is a new value";
|
||||
Assert.assertNotEquals(newValue, annotation.value());
|
||||
AnnotationUtil.setValue(annotation, "value", newValue);
|
||||
Assert.assertEquals(newValue, annotation.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnnotationAlias() {
|
||||
final MetaAnnotationForTest annotation = AnnotationUtil.getAnnotationAlias(AnnotationForTest.class, MetaAnnotationForTest.class);
|
||||
Assert.assertEquals(annotation.value(), annotation.alias());
|
||||
Assert.assertEquals(MetaAnnotationForTest.class, annotation.annotationType());
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface MetaAnnotationForTest{
|
||||
@Alias(value = "alias")
|
||||
String value() default "";
|
||||
String alias() default "";
|
||||
}
|
||||
|
||||
@MetaAnnotationForTest("foo")
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface AnnotationForTest{
|
||||
String value() default "";
|
||||
}
|
||||
|
||||
@AnnotationForTest("foo")
|
||||
private static class ClassForTest{}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,60 @@
|
||||
package cn.hutool.core.annotation;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* test for {@link CombinationAnnotationElement}
|
||||
*/
|
||||
public class CombinationAnnotationElementTest {
|
||||
|
||||
@Test
|
||||
public void testOf() {
|
||||
CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true);
|
||||
Assert.assertNotNull(element);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAnnotationPresent() {
|
||||
CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true);
|
||||
Assert.assertTrue(element.isAnnotationPresent(MetaAnnotationForTest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnnotation() {
|
||||
AnnotationForTest annotation1 = ClassForTest.class.getAnnotation(AnnotationForTest.class);
|
||||
MetaAnnotationForTest annotation2 = AnnotationForTest.class.getAnnotation(MetaAnnotationForTest.class);
|
||||
CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true);
|
||||
Assert.assertEquals(annotation1, element.getAnnotation(AnnotationForTest.class));
|
||||
Assert.assertEquals(annotation2, element.getAnnotation(MetaAnnotationForTest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnnotations() {
|
||||
CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true);
|
||||
Annotation[] annotations = element.getAnnotations();
|
||||
Assert.assertEquals(2, annotations.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDeclaredAnnotations() {
|
||||
CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true);
|
||||
Annotation[] annotations = element.getDeclaredAnnotations();
|
||||
Assert.assertEquals(2, annotations.length);
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface MetaAnnotationForTest{ }
|
||||
|
||||
@MetaAnnotationForTest
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface AnnotationForTest{ }
|
||||
|
||||
@AnnotationForTest
|
||||
private static class ClassForTest{}
|
||||
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package cn.hutool.core.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author hongda.li 2022-04-26 17:09
|
||||
*/
|
||||
@AnnotationForTest("repeat-annotation")
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
// Target注解决定MyAnnotation注解可以加在哪些成分上,如加在类身上,或者属性身上,或者方法身上等成分
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
public @interface RepeatAnnotationForTest {
|
||||
}
|
@ -4,6 +4,7 @@ import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class WeekTest {
|
||||
|
||||
@ -46,6 +47,9 @@ public class WeekTest {
|
||||
Assert.assertEquals(Week.THURSDAY, Week.of(DayOfWeek.THURSDAY));
|
||||
Assert.assertEquals(Week.FRIDAY, Week.of(DayOfWeek.FRIDAY));
|
||||
Assert.assertEquals(Week.SATURDAY, Week.of(DayOfWeek.SATURDAY));
|
||||
Assert.assertEquals(Week.SATURDAY, Week.of(Calendar.SATURDAY));
|
||||
Assert.assertNull(Week.of(10));
|
||||
Assert.assertNull(Week.of(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -58,4 +62,17 @@ public class WeekTest {
|
||||
Assert.assertEquals(DayOfWeek.SATURDAY, Week.SATURDAY.toJdkDayOfWeek());
|
||||
Assert.assertEquals(DayOfWeek.SUNDAY, Week.SUNDAY.toJdkDayOfWeek());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toChineseTest(){
|
||||
Assert.assertEquals("周一",Week.MONDAY.toChinese("周"));
|
||||
Assert.assertEquals("星期一",Week.MONDAY.toChinese("星期"));
|
||||
Assert.assertEquals("星期二",Week.TUESDAY.toChinese("星期"));
|
||||
Assert.assertEquals("星期三",Week.WEDNESDAY.toChinese("星期"));
|
||||
Assert.assertEquals("星期四",Week.THURSDAY.toChinese("星期"));
|
||||
Assert.assertEquals("星期五",Week.FRIDAY.toChinese("星期"));
|
||||
Assert.assertEquals("星期六",Week.SATURDAY.toChinese("星期"));
|
||||
Assert.assertEquals("星期日",Week.SUNDAY.toChinese("星期"));
|
||||
Assert.assertEquals("星期一",Week.MONDAY.toChinese());
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,9 @@ package cn.hutool.core.date;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
public class ZodiacTest {
|
||||
|
||||
@Test
|
||||
@ -10,6 +13,11 @@ public class ZodiacTest {
|
||||
Assert.assertEquals("摩羯座", Zodiac.getZodiac(Month.JANUARY, 19));
|
||||
Assert.assertEquals("水瓶座", Zodiac.getZodiac(Month.JANUARY, 20));
|
||||
Assert.assertEquals("巨蟹座", Zodiac.getZodiac(6, 17));
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(2022, Calendar.JULY, 17);
|
||||
Assert.assertEquals("巨蟹座", Zodiac.getZodiac(calendar.getTime()));
|
||||
Assert.assertEquals("巨蟹座", Zodiac.getZodiac(calendar));
|
||||
Assert.assertNull(Zodiac.getZodiac((Calendar) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -17,5 +25,11 @@ public class ZodiacTest {
|
||||
Assert.assertEquals("狗", Zodiac.getChineseZodiac(1994));
|
||||
Assert.assertEquals("狗", Zodiac.getChineseZodiac(2018));
|
||||
Assert.assertEquals("猪", Zodiac.getChineseZodiac(2019));
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(2022, Calendar.JULY, 17);
|
||||
Assert.assertEquals("虎", Zodiac.getChineseZodiac(calendar.getTime()));
|
||||
Assert.assertEquals("虎", Zodiac.getChineseZodiac(calendar));
|
||||
Assert.assertNull(Zodiac.getChineseZodiac(1899));
|
||||
Assert.assertNull(Zodiac.getChineseZodiac((Calendar) null));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package cn.hutool.core.date;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class ZoneUtilTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
Assert.assertEquals(ZoneId.systemDefault(), ZoneUtil.toZoneId(null));
|
||||
Assert.assertEquals(TimeZone.getDefault(), ZoneUtil.toTimeZone(null));
|
||||
}
|
||||
}
|
@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,18 +1,16 @@
|
||||
package cn.hutool.core.util;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.exceptions.CloneRuntimeException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ObjUtilTest {
|
||||
|
||||
@ -84,7 +82,7 @@ public class ObjUtilTest {
|
||||
public Obj clone() {
|
||||
try {
|
||||
return (Obj) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
throw new CloneRuntimeException(e);
|
||||
}
|
||||
}
|
||||
@ -99,15 +97,20 @@ public class ObjUtilTest {
|
||||
|
||||
@Test
|
||||
public void defaultIfNullTest() {
|
||||
final String dateStr = "2020-10-23 15:12:30";
|
||||
final Instant result1 = ObjUtil.defaultIfNull(dateStr,
|
||||
(v) -> DateUtil.parse(v.toString(), DatePattern.NORM_DATETIME_PATTERN).toInstant(), Instant::now);
|
||||
Assert.assertNotNull(result1);
|
||||
final Object val1 = new Object();
|
||||
final Object val2 = new Object();
|
||||
|
||||
final String nullValue = null;
|
||||
final Instant result2 = ObjUtil.defaultIfNull(nullValue,
|
||||
(v) -> DateUtil.parse(v.toString(), DatePattern.NORM_DATETIME_PATTERN).toInstant(), Instant::now);
|
||||
Assert.assertNotNull(result2);
|
||||
Assert.assertSame(val1, ObjUtil.defaultIfNull(val1, () -> val2));
|
||||
Assert.assertSame(val2, ObjUtil.defaultIfNull(null, () -> val2));
|
||||
|
||||
Assert.assertSame(val1, ObjUtil.defaultIfNull(val1, val2));
|
||||
Assert.assertSame(val2, ObjUtil.defaultIfNull(null, val2));
|
||||
|
||||
Assert.assertSame(val1, ObjUtil.defaultIfNull(val1, Function.identity(), () -> val2));
|
||||
Assert.assertSame(val2, ObjUtil.defaultIfNull(null, Function.identity(), () -> val2));
|
||||
|
||||
Assert.assertSame(val1, ObjUtil.defaultIfNull(val1, Function.identity(), val2));
|
||||
Assert.assertSame(val2, ObjUtil.defaultIfNull(null, Function.identity(), val2));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -119,7 +122,7 @@ public class ObjUtilTest {
|
||||
|
||||
@Test
|
||||
public void cloneIfPossibleTest() {
|
||||
String a = "a";
|
||||
final String a = "a";
|
||||
final String a2 = ObjUtil.cloneIfPossible(a);
|
||||
Assert.assertNotSame(a, a2);
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -303,7 +302,7 @@ public class HttpServerRequest extends HttpServerBase {
|
||||
* @since 5.5.8
|
||||
*/
|
||||
public String getParam(final String name){
|
||||
return getParams().get(name, 0);
|
||||
return getParams().getValue(name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -313,7 +312,7 @@ public class HttpServerRequest extends HttpServerBase {
|
||||
* @return 参数值
|
||||
* @since 5.5.8
|
||||
*/
|
||||
public List<String> getParams(final String name){
|
||||
public Collection<String> getParams(final String name){
|
||||
return getParams().get(name);
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import cn.hutool.core.bean.BeanPath;
|
||||
import cn.hutool.core.lang.mutable.MutableEntry;
|
||||
import cn.hutool.json.convert.JSONConverterOld;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* JSON接口
|
||||
@ -23,6 +25,13 @@ public interface JSON extends Cloneable, Serializable {
|
||||
*/
|
||||
JSONConfig getConfig();
|
||||
|
||||
/**
|
||||
* JSON大小,对于JSONObject,是键值对的多少,JSONArray则是元素的个数
|
||||
*
|
||||
* @return 大小
|
||||
*/
|
||||
int size();
|
||||
|
||||
/**
|
||||
* 通过表达式获取JSON中嵌套的对象<br>
|
||||
* <ol>
|
||||
@ -44,7 +53,7 @@ public interface JSON extends Cloneable, Serializable {
|
||||
* @see BeanPath#get(Object)
|
||||
* @since 4.0.6
|
||||
*/
|
||||
default Object getByPath(final String expression){
|
||||
default Object getByPath(final String expression) {
|
||||
return BeanPath.of(expression).get(this);
|
||||
}
|
||||
|
||||
@ -69,7 +78,7 @@ public interface JSON extends Cloneable, Serializable {
|
||||
* @param expression 表达式
|
||||
* @param value 值
|
||||
*/
|
||||
default void putByPath(final String expression, final Object value){
|
||||
default void putByPath(final String expression, final Object value) {
|
||||
BeanPath.of(expression).set(this, value);
|
||||
}
|
||||
|
||||
@ -121,7 +130,7 @@ public interface JSON extends Cloneable, Serializable {
|
||||
default String toJSONString(final int indentFactor) throws JSONException {
|
||||
final StringWriter sw = new StringWriter();
|
||||
synchronized (sw.getBuffer()) {
|
||||
return this.write(sw, indentFactor, 0).toString();
|
||||
return this.write(sw, indentFactor, 0, null).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,7 +143,7 @@ public interface JSON extends Cloneable, Serializable {
|
||||
* @throws JSONException JSON相关异常
|
||||
*/
|
||||
default Writer write(final Writer writer) throws JSONException {
|
||||
return this.write(writer, 0, 0);
|
||||
return this.write(writer, 0, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,10 +153,11 @@ public interface JSON extends Cloneable, Serializable {
|
||||
* @param writer writer
|
||||
* @param indentFactor 缩进因子,定义每一级别增加的缩进量
|
||||
* @param indent 本级别缩进量
|
||||
* @param predicate 过滤器,可以修改值,key(index)无法修改,{@link Predicate#test(Object)}为{@code true}保留
|
||||
* @return Writer
|
||||
* @throws JSONException JSON相关异常
|
||||
*/
|
||||
Writer write(Writer writer, int indentFactor, int indent) throws JSONException;
|
||||
Writer write(Writer writer, int indentFactor, int indent, final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException;
|
||||
|
||||
/**
|
||||
* 转为实体类对象,转换异常将被抛出
|
||||
@ -163,8 +173,8 @@ public interface JSON extends Cloneable, Serializable {
|
||||
/**
|
||||
* 转为实体类对象
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param type {@link Type}
|
||||
* @param <T> Bean类型
|
||||
* @param type {@link Type}
|
||||
* @return 实体类对象
|
||||
* @since 4.3.2
|
||||
*/
|
||||
|
@ -533,7 +533,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
|
||||
* @return JSON字符串
|
||||
* @since 5.7.15
|
||||
*/
|
||||
public String toJSONString(final int indentFactor, final Predicate<MutableEntry<Integer, Object>> predicate) {
|
||||
public String toJSONString(final int indentFactor, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||
final StringWriter sw = new StringWriter();
|
||||
synchronized (sw.getBuffer()) {
|
||||
return this.write(sw, indentFactor, 0, predicate).toString();
|
||||
@ -541,32 +541,10 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer write(final Writer writer, final int indentFactor, final int indent) throws JSONException {
|
||||
return write(writer, indentFactor, indent, null);
|
||||
}
|
||||
public Writer write(final Writer writer, final int indentFactor, final int indent, final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException {
|
||||
final JSONWriter jsonWriter = JSONWriter.of(writer, indentFactor, indent, config).beginArray();
|
||||
|
||||
/**
|
||||
* 将JSON内容写入Writer<br>
|
||||
* 支持过滤器,即选择哪些字段或值不写出
|
||||
*
|
||||
* @param writer writer
|
||||
* @param indentFactor 缩进因子,定义每一级别增加的缩进量
|
||||
* @param indent 本级别缩进量
|
||||
* @param predicate 过滤器,可以修改值,key(index)无法修改,{@link Predicate#test(Object)}为{@code true}保留
|
||||
* @return Writer
|
||||
* @throws JSONException JSON相关异常
|
||||
* @since 5.7.15
|
||||
*/
|
||||
public Writer write(final Writer writer, final int indentFactor, final int indent, final Predicate<MutableEntry<Integer, Object>> predicate) throws JSONException {
|
||||
final JSONWriter jsonWriter = JSONWriter.of(writer, indentFactor, indent, config)
|
||||
.beginArray();
|
||||
|
||||
CollUtil.forEach(this, (value, index) -> {
|
||||
final MutableEntry<Integer, Object> pair = new MutableEntry<>(index, value);
|
||||
if (null == predicate || predicate.test(pair)) {
|
||||
jsonWriter.writeValue(pair.getValue());
|
||||
}
|
||||
});
|
||||
CollUtil.forEach(this, (value, index) -> jsonWriter.writeField(new MutableEntry<>(index, value), predicate));
|
||||
jsonWriter.end();
|
||||
// 此处不关闭Writer,考虑writer后续还需要填内容
|
||||
return writer;
|
||||
|
@ -341,18 +341,13 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
|
||||
* @return JSON字符串
|
||||
* @since 5.7.15
|
||||
*/
|
||||
public String toJSONString(final int indentFactor, final Predicate<MutableEntry<String, Object>> predicate) {
|
||||
public String toJSONString(final int indentFactor, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||
final StringWriter sw = new StringWriter();
|
||||
synchronized (sw.getBuffer()) {
|
||||
return this.write(sw, indentFactor, 0, predicate).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer write(final Writer writer, final int indentFactor, final int indent) throws JSONException {
|
||||
return write(writer, indentFactor, indent, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将JSON内容写入Writer<br>
|
||||
* 支持过滤器,即选择哪些字段或值不写出
|
||||
@ -365,20 +360,11 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
|
||||
* @throws JSONException JSON相关异常
|
||||
* @since 5.7.15
|
||||
*/
|
||||
public Writer write(final Writer writer, final int indentFactor, final int indent, final Predicate<MutableEntry<String, Object>> predicate) throws JSONException {
|
||||
@Override
|
||||
public Writer write(final Writer writer, final int indentFactor, final int indent, final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException {
|
||||
final JSONWriter jsonWriter = JSONWriter.of(writer, indentFactor, indent, config)
|
||||
.beginObj();
|
||||
this.forEach((key, value) -> {
|
||||
if (null != predicate) {
|
||||
final MutableEntry<String, Object> pair = new MutableEntry<>(key, value);
|
||||
if (predicate.test(pair)) {
|
||||
// 使用修改后的键值对
|
||||
jsonWriter.writeField(pair.getKey(), pair.getValue());
|
||||
}
|
||||
} else {
|
||||
jsonWriter.writeField(key, value);
|
||||
}
|
||||
});
|
||||
this.forEach((key, value) -> jsonWriter.writeField(new MutableEntry<>(key, value), predicate));
|
||||
jsonWriter.end();
|
||||
// 此处不关闭Writer,考虑writer后续还需要填内容
|
||||
return writer;
|
||||
|
@ -530,32 +530,6 @@ public class JSONUtil {
|
||||
return (T) json.getByPath(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置表达式指定位置(或filed对应)的值<br>
|
||||
* 若表达式指向一个JSONArray则设置其坐标对应位置的值,若指向JSONObject则put对应key的值<br>
|
||||
* 注意:如果为JSONArray,则设置值得下标不能大于已有JSONArray的长度<br>
|
||||
* <ol>
|
||||
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* 表达式栗子:
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
* persons[3]
|
||||
* person.friends[5].name
|
||||
* </pre>
|
||||
*
|
||||
* @param json JSON,可以为JSONObject或JSONArray
|
||||
* @param expression 表达式
|
||||
* @param value 值
|
||||
*/
|
||||
public static void putByPath(final JSON json, final String expression, final Object value) {
|
||||
json.putByPath(expression, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化JSON字符串,此方法并不严格检查JSON的格式正确与否
|
||||
*
|
||||
|
@ -23,6 +23,10 @@ public class AlgorithmUtil {
|
||||
map.put("HS384", HmacAlgorithm.HmacSHA384.getValue());
|
||||
map.put("HS512", HmacAlgorithm.HmacSHA512.getValue());
|
||||
|
||||
map.put("HMD5", HmacAlgorithm.HmacMD5.getValue());
|
||||
map.put("HSHA1", HmacAlgorithm.HmacSHA1.getValue());
|
||||
map.put("SM4CMAC", HmacAlgorithm.SM4CMAC.getValue());
|
||||
|
||||
map.put("RS256", SignAlgorithm.SHA256withRSA.getValue());
|
||||
map.put("RS384", SignAlgorithm.SHA384withRSA.getValue());
|
||||
map.put("RS512", SignAlgorithm.SHA512withRSA.getValue());
|
||||
@ -34,6 +38,14 @@ public class AlgorithmUtil {
|
||||
map.put("PS256", SignAlgorithm.SHA256withRSA_PSS.getValue());
|
||||
map.put("PS384", SignAlgorithm.SHA384withRSA_PSS.getValue());
|
||||
map.put("PS512", SignAlgorithm.SHA512withRSA_PSS.getValue());
|
||||
|
||||
map.put("RMD2", SignAlgorithm.MD2withRSA.getValue());
|
||||
map.put("RMD5", SignAlgorithm.MD5withRSA.getValue());
|
||||
map.put("RSHA1", SignAlgorithm.SHA1withRSA.getValue());
|
||||
map.put("DNONE", SignAlgorithm.NONEwithDSA.getValue());
|
||||
map.put("DSHA1", SignAlgorithm.SHA1withDSA.getValue());
|
||||
map.put("ENONE", SignAlgorithm.NONEwithECDSA.getValue());
|
||||
map.put("ESHA1", SignAlgorithm.SHA1withECDSA.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,6 +120,106 @@ public class JWTSignerUtil {
|
||||
return createSigner("ES512", key);
|
||||
}
|
||||
|
||||
/**
|
||||
* HMD5(HmacMD5)签名器
|
||||
*
|
||||
* @param key 密钥
|
||||
* @return 签名器
|
||||
*/
|
||||
public static JWTSigner hmd5(final Key key) {
|
||||
return createSigner("HMD5",key);
|
||||
}
|
||||
|
||||
/**
|
||||
* HSHA1(HmacSHA1)签名器
|
||||
*
|
||||
* @param key 密钥
|
||||
* @return 签名器
|
||||
*/
|
||||
public static JWTSigner hsha1(final Key key) {
|
||||
return createSigner("HSHA1",key);
|
||||
}
|
||||
|
||||
/**
|
||||
* SM4CMAC(SM4CMAC)签名器
|
||||
*
|
||||
* @param key 密钥
|
||||
* @return 签名器
|
||||
*/
|
||||
public static JWTSigner sm4cmac(final Key key) {
|
||||
return createSigner("SM4CMAC",key);
|
||||
}
|
||||
|
||||
/**
|
||||
* RMD2(MD2withRSA)签名器
|
||||
*
|
||||
* @param key 密钥
|
||||
* @return 签名器
|
||||
*/
|
||||
public static JWTSigner rmd2(final Key key) {
|
||||
return createSigner("RMD2",key);
|
||||
}
|
||||
|
||||
/**
|
||||
* RMD5(MD5withRSA)签名器
|
||||
*
|
||||
* @param key 密钥
|
||||
* @return 签名器
|
||||
*/
|
||||
public static JWTSigner rmd5(final Key key) {
|
||||
return createSigner("RMD5",key);
|
||||
}
|
||||
|
||||
/**
|
||||
* RSHA1(SHA1withRSA)签名器
|
||||
*
|
||||
* @param key 密钥
|
||||
* @return 签名器
|
||||
*/
|
||||
public static JWTSigner rsha1(final Key key) {
|
||||
return createSigner("RSHA1",key);
|
||||
}
|
||||
|
||||
/**
|
||||
* DNONE(NONEwithDSA)签名器
|
||||
*
|
||||
* @param key 密钥
|
||||
* @return 签名器
|
||||
*/
|
||||
public static JWTSigner dnone(final Key key) {
|
||||
return createSigner("DNONE",key);
|
||||
}
|
||||
|
||||
/**
|
||||
* DSHA1(SHA1withDSA)签名器
|
||||
*
|
||||
* @param key 密钥
|
||||
* @return 签名器
|
||||
*/
|
||||
public static JWTSigner dsha1(final Key key) {
|
||||
return createSigner("DSHA1",key);
|
||||
}
|
||||
|
||||
/**
|
||||
* ENONE(NONEwithECDSA)签名器
|
||||
*
|
||||
* @param key 密钥
|
||||
* @return 签名器
|
||||
*/
|
||||
public static JWTSigner enone(final Key key) {
|
||||
return createSigner("ENONE",key);
|
||||
}
|
||||
|
||||
/**
|
||||
* ESHA1(SHA1withECDSA)签名器
|
||||
*
|
||||
* @param key 密钥
|
||||
* @return 签名器
|
||||
*/
|
||||
public static JWTSigner esha1(final Key key) {
|
||||
return createSigner("ESHA1",key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建签名器
|
||||
*
|
||||
|
@ -5,6 +5,7 @@ import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.date.TemporalAccessorUtil;
|
||||
import cn.hutool.core.date.format.GlobalCustomFormat;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.lang.mutable.MutableEntry;
|
||||
import cn.hutool.core.math.NumberUtil;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import cn.hutool.core.util.CharUtil;
|
||||
@ -15,9 +16,11 @@ import cn.hutool.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.time.MonthDay;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* JSON数据写出器<br>
|
||||
@ -123,54 +126,54 @@ public class JSONWriter extends Writer {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写出字段名及字段值,如果字段值是{@code null}且忽略null值,则不写出任何内容<br>
|
||||
* 在{@link #arrayMode} 为 {@code true} 时,key是数字,此时不写出键,只写值
|
||||
*
|
||||
* @param pair 键值对
|
||||
* @param predicate 过滤修改器
|
||||
* @return this
|
||||
* @since 6.0.0
|
||||
*/
|
||||
@SuppressWarnings({"UnusedReturnValue", "resource"})
|
||||
public JSONWriter writeField(final MutableEntry<Object, Object> pair, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||
if (null == pair.getValue() && config.isIgnoreNullValue()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (null != predicate) {
|
||||
if (false == predicate.test(pair)) {
|
||||
// 使用修改后的键值对
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
if(false == arrayMode){
|
||||
// JSONObject模式,写出键,否则只输出值
|
||||
writeKey(StrUtil.toString(pair.getKey()));
|
||||
}
|
||||
|
||||
return writeValueDirect(pair.getValue(), predicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 写出键,自动处理分隔符和缩进,并包装键名
|
||||
*
|
||||
* @param key 键名
|
||||
* @return this
|
||||
*/
|
||||
@SuppressWarnings({"resource", "UnusedReturnValue"})
|
||||
public JSONWriter writeKey(final String key) {
|
||||
if (needSeparator) {
|
||||
//noinspection resource
|
||||
writeRaw(CharUtil.COMMA);
|
||||
}
|
||||
// 换行缩进
|
||||
//noinspection resource
|
||||
writeLF().writeSpace(indentFactor + indent);
|
||||
return writeRaw(InternalJSONUtil.quote(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* 写出值,自动处理分隔符和缩进,自动判断类型,并根据不同类型写出特定格式的值<br>
|
||||
* 如果写出的值为{@code null},且配置忽略null,则跳过。
|
||||
*
|
||||
* @param value 值
|
||||
* @return this
|
||||
*/
|
||||
public JSONWriter writeValue(final Object value) {
|
||||
if (null == value && config.isIgnoreNullValue()) {
|
||||
return this;
|
||||
}
|
||||
return writeValueDirect(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 写出字段名及字段值,如果字段值是{@code null}且忽略null值,则不写出任何内容
|
||||
*
|
||||
* @param key 字段名
|
||||
* @param value 字段值
|
||||
* @return this
|
||||
* @since 5.7.6
|
||||
*/
|
||||
public JSONWriter writeField(final String key, final Object value) {
|
||||
if (null == value && config.isIgnoreNullValue()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
//noinspection resource
|
||||
return writeKey(key).writeValueDirect(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"SpellCheckingInspection", "NullableProblems"})
|
||||
@Override
|
||||
public void write(final char[] cbuf, final int off, final int len) throws IOException {
|
||||
this.writer.write(cbuf, off, len);
|
||||
@ -195,10 +198,11 @@ public class JSONWriter extends Writer {
|
||||
/**
|
||||
* 写出值,自动处理分隔符和缩进,自动判断类型,并根据不同类型写出特定格式的值
|
||||
*
|
||||
* @param value 值
|
||||
* @param value 值
|
||||
* @param predicate 过滤修改器
|
||||
* @return this
|
||||
*/
|
||||
private JSONWriter writeValueDirect(final Object value) {
|
||||
private JSONWriter writeValueDirect(final Object value, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||
if (arrayMode) {
|
||||
if (needSeparator) {
|
||||
//noinspection resource
|
||||
@ -212,25 +216,32 @@ public class JSONWriter extends Writer {
|
||||
writeRaw(CharUtil.COLON).writeSpace(1);
|
||||
}
|
||||
needSeparator = true;
|
||||
return writeObjValue(value);
|
||||
return writeObjValue(value, predicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 写出JSON的值,根据值类型不同,输出不同内容
|
||||
*
|
||||
* @param value 值
|
||||
* @param value 值
|
||||
* @param predicate 过滤修改器
|
||||
* @return this
|
||||
*/
|
||||
private JSONWriter writeObjValue(final Object value) {
|
||||
private JSONWriter writeObjValue(final Object value, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||
final int indent = indentFactor + this.indent;
|
||||
if (value == null) {
|
||||
//noinspection resource
|
||||
writeRaw(StrUtil.NULL);
|
||||
} else if (value instanceof JSON) {
|
||||
((JSON) value).write(writer, indentFactor, indent);
|
||||
((JSON) value).write(writer, indentFactor, indent, predicate);
|
||||
} else if (value instanceof Number) {
|
||||
writeNumberValue((Number) value);
|
||||
} else if (value instanceof Date || value instanceof Calendar || value instanceof TemporalAccessor) {
|
||||
// issue#2572@Github
|
||||
if(value instanceof MonthDay){
|
||||
writeQuoteStrValue(value.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
final String format = (null == config) ? null : config.getDateFormat();
|
||||
//noinspection resource
|
||||
writeRaw(formatDate(value, format));
|
||||
|
53
hutool-json/src/test/java/cn/hutool/json/Issue2572Test.java
Executable file
53
hutool-json/src/test/java/cn/hutool/json/Issue2572Test.java
Executable file
@ -0,0 +1,53 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import cn.hutool.core.reflect.TypeReference;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.Month;
|
||||
import java.time.MonthDay;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class Issue2572Test {
|
||||
@Test
|
||||
public void putDayOfWeekTest(){
|
||||
final Set<DayOfWeek> weeks = new HashSet<>();
|
||||
weeks.add(DayOfWeek.MONDAY);
|
||||
final JSONObject obj = new JSONObject();
|
||||
obj.set("weeks", weeks);
|
||||
Assert.assertEquals("{\"weeks\":[1]}", obj.toString());
|
||||
|
||||
final Map<String, Set<DayOfWeek>> monthDays1 = obj.toBean(new TypeReference<Map<String, Set<DayOfWeek>>>() {
|
||||
});
|
||||
Assert.assertEquals("{weeks=[MONDAY]}", monthDays1.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putMonthTest(){
|
||||
final Set<Month> months = new HashSet<>();
|
||||
months.add(Month.DECEMBER);
|
||||
final JSONObject obj = new JSONObject();
|
||||
obj.set("months", months);
|
||||
Assert.assertEquals("{\"months\":[12]}", obj.toString());
|
||||
|
||||
final Map<String, Set<Month>> monthDays1 = obj.toBean(new TypeReference<Map<String, Set<Month>>>() {
|
||||
});
|
||||
Assert.assertEquals("{months=[DECEMBER]}", monthDays1.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putMonthDayTest(){
|
||||
final Set<MonthDay> monthDays = new HashSet<>();
|
||||
monthDays.add(MonthDay.of(Month.DECEMBER, 1));
|
||||
final JSONObject obj = new JSONObject();
|
||||
obj.set("monthDays", monthDays);
|
||||
Assert.assertEquals("{\"monthDays\":[\"--12-01\"]}", obj.toString());
|
||||
|
||||
final Map<String, Set<MonthDay>> monthDays1 = obj.toBean(new TypeReference<Map<String, Set<MonthDay>>>() {
|
||||
});
|
||||
Assert.assertEquals("{monthDays=[--12-01]}", monthDays1.toString());
|
||||
}
|
||||
}
|
26
hutool-json/src/test/java/cn/hutool/json/IssueI5OMSCTest.java
Executable file
26
hutool-json/src/test/java/cn/hutool/json/IssueI5OMSCTest.java
Executable file
@ -0,0 +1,26 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Predicate多层过滤
|
||||
*/
|
||||
public class IssueI5OMSCTest {
|
||||
|
||||
@Test
|
||||
public void filterTest(){
|
||||
final JSONObject json = JSONUtil.parseObj(ResourceUtil.readUtf8Str("issueI5OMSC.json"));
|
||||
|
||||
final String s = json.toJSONString(0, (entry) -> {
|
||||
final Object key = entry.getKey();
|
||||
if(key instanceof String){
|
||||
return ListUtil.of("store", "bicycle", "color", "book", "author").contains(key);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
Assert.assertEquals("{\"store\":{\"bicycle\":{\"color\":\"red\"},\"book\":[{\"author\":\"Evelyn Waugh\"},{\"author\":\"Evelyn Waugh02\"}]}}", s);
|
||||
}
|
||||
}
|
@ -700,7 +700,7 @@ public class JSONObjectTest {
|
||||
.set("d", true);
|
||||
|
||||
final String s = json1.toJSONString(0, (pair) -> {
|
||||
pair.setKey(StrUtil.toUnderlineCase(pair.getKey()));
|
||||
pair.setKey(StrUtil.toUnderlineCase((String)pair.getKey()));
|
||||
return true;
|
||||
});
|
||||
Assert.assertEquals("{\"a_key\":\"value1\",\"b_job\":\"value2\",\"c_good\":\"value3\",\"d\":true}", s);
|
||||
|
@ -116,6 +116,96 @@ public class JWTSignerTest {
|
||||
signAndVerify(signer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hmd5Test(){
|
||||
final String id = "hmd5";
|
||||
final JWTSigner signer = JWTSignerUtil.createSigner(id, KeyUtil.generateKey(AlgorithmUtil.getAlgorithm(id)));
|
||||
Assert.assertEquals(AlgorithmUtil.getAlgorithm(id), signer.getAlgorithm());
|
||||
|
||||
signAndVerify(signer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hsha1Test(){
|
||||
final String id = "hsha1";
|
||||
final JWTSigner signer = JWTSignerUtil.createSigner(id, KeyUtil.generateKey(AlgorithmUtil.getAlgorithm(id)));
|
||||
Assert.assertEquals(AlgorithmUtil.getAlgorithm(id), signer.getAlgorithm());
|
||||
|
||||
signAndVerify(signer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sm4cmacTest(){
|
||||
final String id = "sm4cmac";
|
||||
final JWTSigner signer = JWTSignerUtil.createSigner(id, KeyUtil.generateKey(AlgorithmUtil.getAlgorithm(id)));
|
||||
Assert.assertEquals(AlgorithmUtil.getAlgorithm(id), signer.getAlgorithm());
|
||||
|
||||
signAndVerify(signer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rmd2Test(){
|
||||
final String id = "rmd2";
|
||||
final JWTSigner signer = JWTSignerUtil.createSigner(id, KeyUtil.generateKeyPair(AlgorithmUtil.getAlgorithm(id)));
|
||||
Assert.assertEquals(AlgorithmUtil.getAlgorithm(id), signer.getAlgorithm());
|
||||
|
||||
signAndVerify(signer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rmd5Test(){
|
||||
final String id = "rmd5";
|
||||
final JWTSigner signer = JWTSignerUtil.createSigner(id, KeyUtil.generateKeyPair(AlgorithmUtil.getAlgorithm(id)));
|
||||
Assert.assertEquals(AlgorithmUtil.getAlgorithm(id), signer.getAlgorithm());
|
||||
|
||||
signAndVerify(signer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rsha1Test(){
|
||||
final String id = "rsha1";
|
||||
final JWTSigner signer = JWTSignerUtil.createSigner(id, KeyUtil.generateKeyPair(AlgorithmUtil.getAlgorithm(id)));
|
||||
Assert.assertEquals(AlgorithmUtil.getAlgorithm(id), signer.getAlgorithm());
|
||||
|
||||
signAndVerify(signer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dnoneTest(){
|
||||
final String id = "dnone";
|
||||
final JWTSigner signer = JWTSignerUtil.createSigner(id, KeyUtil.generateKeyPair(AlgorithmUtil.getAlgorithm(id)));
|
||||
Assert.assertEquals(AlgorithmUtil.getAlgorithm(id), signer.getAlgorithm());
|
||||
|
||||
signAndVerify(signer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dsha1Test(){
|
||||
final String id = "dsha1";
|
||||
final JWTSigner signer = JWTSignerUtil.createSigner(id, KeyUtil.generateKeyPair(AlgorithmUtil.getAlgorithm(id)));
|
||||
Assert.assertEquals(AlgorithmUtil.getAlgorithm(id), signer.getAlgorithm());
|
||||
|
||||
signAndVerify(signer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enoneTest(){
|
||||
final String id = "enone";
|
||||
final JWTSigner signer = JWTSignerUtil.createSigner(id, KeyUtil.generateKeyPair(AlgorithmUtil.getAlgorithm(id)));
|
||||
Assert.assertEquals(AlgorithmUtil.getAlgorithm(id), signer.getAlgorithm());
|
||||
|
||||
signAndVerify(signer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void esha1Test(){
|
||||
final String id = "esha1";
|
||||
final JWTSigner signer = JWTSignerUtil.createSigner(id, KeyUtil.generateKeyPair(AlgorithmUtil.getAlgorithm(id)));
|
||||
Assert.assertEquals(AlgorithmUtil.getAlgorithm(id), signer.getAlgorithm());
|
||||
|
||||
signAndVerify(signer);
|
||||
}
|
||||
|
||||
private static void signAndVerify(final JWTSigner signer){
|
||||
final JWT jwt = JWT.of()
|
||||
.setPayload("sub", "1234567890")
|
||||
|
32
hutool-json/src/test/resources/issueI5OMSC.json
Executable file
32
hutool-json/src/test/resources/issueI5OMSC.json
Executable file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"store": {
|
||||
"bicycle": {
|
||||
"color": "red",
|
||||
"price": 19.95
|
||||
},
|
||||
"book": [
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "Evelyn Waugh",
|
||||
"title": "Sword of Honour",
|
||||
"price": 12.99,
|
||||
"items": [
|
||||
{
|
||||
"name": "wujing001",
|
||||
"age": 18
|
||||
},
|
||||
{
|
||||
"name": "wujing002",
|
||||
"age": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "fiction02",
|
||||
"author": "Evelyn Waugh02",
|
||||
"title": "Sword of Honour02",
|
||||
"price": 12.99
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -44,7 +44,9 @@ public class MapSheetReader extends AbstractSheetReader<List<Map<String, Object>
|
||||
if (headerRowIndex < firstRowNum) {
|
||||
throw new IndexOutOfBoundsException(StrUtil.format("Header row index {} is lower than first row index {}.", headerRowIndex, firstRowNum));
|
||||
} else if (headerRowIndex > lastRowNum) {
|
||||
throw new IndexOutOfBoundsException(StrUtil.format("Header row index {} is greater than last row index {}.", headerRowIndex, firstRowNum));
|
||||
throw new IndexOutOfBoundsException(StrUtil.format("Header row index {} is greater than last row index {}.", headerRowIndex, lastRowNum));
|
||||
} else if (startRowIndex > lastRowNum) {
|
||||
throw new IndexOutOfBoundsException(StrUtil.format("startRowIndex row index {} is greater than last row index {}.", startRowIndex, lastRowNum));
|
||||
}
|
||||
final int startRowIndex = Math.max(this.startRowIndex, firstRowNum);// 读取起始行(包含)
|
||||
final int endRowIndex = Math.min(this.endRowIndex, lastRowNum);// 读取结束行(包含)
|
||||
|
@ -251,4 +251,21 @@ public class ExcelReadTest {
|
||||
final ExcelReader reader = ExcelUtil.getReader(ResourceUtil.getStream("read_row_npe.xlsx"));
|
||||
reader.readColumn(0, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readIssueTest() {
|
||||
//https://gitee.com/dromara/hutool/issues/I5OSFC
|
||||
final ExcelReader reader = ExcelUtil.getReader(ResourceUtil.getStream("read.xlsx"));
|
||||
final List<Map<String, Object>> read = reader.read(1,2,2);
|
||||
for (Map<String, Object> map : read) {
|
||||
Console.log(map);
|
||||
}
|
||||
//超出lastIndex 抛出相应提示:startRowIndex row index 4 is greater than last row index 2.
|
||||
//而非:Illegal Capacity: -1
|
||||
try {
|
||||
final List<Map<String, Object>> readGreaterIndex = reader.read(1,4,4);
|
||||
} catch (Exception e) {
|
||||
Console.log(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
BIN
hutool-poi/src/test/resources/read.xlsx
Normal file
BIN
hutool-poi/src/test/resources/read.xlsx
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user