mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-30 12:47:58 +08:00
Merge branch 'v6-dev' into refactor-stream
# Conflicts: # hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java # hutool-core/src/main/java/cn/hutool/core/stream/WrappedStream.java
This commit is contained in:
commit
b463b11364
@ -3,6 +3,7 @@ package cn.hutool.core.collection.iter;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 数组Iterator对象
|
||||
@ -75,7 +76,7 @@ public class ArrayIter<E> implements IterableIter<E>, ResettableIter<E>, Seriali
|
||||
* @throws NullPointerException array对象为null
|
||||
*/
|
||||
public ArrayIter(final Object array, final int startIndex, final int endIndex) {
|
||||
this.endIndex = Array.getLength(array);
|
||||
this.endIndex = Array.getLength(Objects.requireNonNull(array));
|
||||
if (endIndex > 0 && endIndex < this.endIndex) {
|
||||
this.endIndex = endIndex;
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@ -39,12 +41,12 @@ public class CopiedIter<E> implements IterableIter<E>, Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* 构造,当{@code iterator}为空时,默认复制一个空迭代器
|
||||
*
|
||||
* @param iterator 被复制的Iterator
|
||||
*/
|
||||
public CopiedIter(final Iterator<E> iterator) {
|
||||
final List<E> eleList = ListUtil.of(iterator);
|
||||
final List<E> eleList = ListUtil.of(ObjUtil.defaultIfNull(iterator, Collections.emptyIterator()));
|
||||
this.listIterator = eleList.iterator();
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import cn.hutool.core.collection.iter.IterableIter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
|
@ -32,6 +32,7 @@ public class FilterIter<E> implements Iterator<E> {
|
||||
*
|
||||
* @param iterator 被包装的{@link Iterator}
|
||||
* @param filter 过滤函数,{@code null}表示不过滤
|
||||
* @throws NullPointerException {@code iterator}为{@code null}时抛出
|
||||
*/
|
||||
public FilterIter(final Iterator<? extends E> iterator, final Predicate<? super E> filter) {
|
||||
this.iterator = Assert.notNull(iterator);
|
||||
|
@ -1,11 +1,9 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import cn.hutool.core.lang.Chain;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 组合{@link Iterator},将多个{@link Iterator}组合在一起,便于集中遍历。<br>
|
||||
@ -28,16 +26,27 @@ public class IterChain<T> implements Iterator<T>, Chain<Iterator<T>, IterChain<T
|
||||
/**
|
||||
* 构造
|
||||
* @param iterators 多个{@link Iterator}
|
||||
* @throws IllegalArgumentException 当存在重复的迭代器,或添加的迭代器中存在{@code null}时抛出
|
||||
*/
|
||||
@SafeVarargs
|
||||
public IterChain(final Iterator<T>... iterators) {
|
||||
for (final Iterator<T> iterator : iterators) {
|
||||
addChain(iterator);
|
||||
if (ArrayUtil.isNotEmpty(iterators)) {
|
||||
for (final Iterator<T> iterator : iterators) {
|
||||
addChain(iterator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加迭代器
|
||||
*
|
||||
* @param iterator 迭代器
|
||||
* @return 当前实例
|
||||
* @throws IllegalArgumentException 当迭代器被重复添加,或待添加的迭代器为{@code null}时抛出
|
||||
*/
|
||||
@Override
|
||||
public IterChain<T> addChain(final Iterator<T> iterator) {
|
||||
Objects.requireNonNull(iterator);
|
||||
if (allIterators.contains(iterator)) {
|
||||
throw new IllegalArgumentException("Duplicate iterator");
|
||||
}
|
||||
|
@ -11,16 +11,7 @@ import cn.hutool.core.util.ObjUtil;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Dictionary;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
@ -192,32 +183,35 @@ public class IterUtil {
|
||||
/**
|
||||
* 获取指定Bean列表中某个字段,生成新的列表
|
||||
*
|
||||
* @param <R> 返回元素类型
|
||||
* @param <V> 对象类型
|
||||
* @param iterable 对象列表
|
||||
* @param fieldName 字段名(会通过反射获取其值)
|
||||
* @return 某个字段值与对象对应Map
|
||||
* @since 4.6.2
|
||||
*/
|
||||
public static <V> List<Object> fieldValueList(final Iterable<V> iterable, final String fieldName) {
|
||||
public static <V, R> List<R> fieldValueList(final Iterable<V> iterable, final String fieldName) {
|
||||
return fieldValueList(getIter(iterable), fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定Bean列表中某个字段,生成新的列表
|
||||
*
|
||||
* @param <R> 返回元素类型
|
||||
* @param <V> 对象类型
|
||||
* @param iter 对象列表
|
||||
* @param fieldName 字段名(会通过反射获取其值)
|
||||
* @return 某个字段值与对象对应Map
|
||||
* @since 4.0.10
|
||||
*/
|
||||
public static <V> List<Object> fieldValueList(final Iterator<V> iter, final String fieldName) {
|
||||
final List<Object> result = new ArrayList<>();
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <V, R> List<R> fieldValueList(final Iterator<V> iter, final String fieldName) {
|
||||
final List<R> result = new ArrayList<>();
|
||||
if (null != iter) {
|
||||
V value;
|
||||
while (iter.hasNext()) {
|
||||
value = iter.next();
|
||||
result.add(FieldUtil.getFieldValue(value, fieldName));
|
||||
result.add((R)FieldUtil.getFieldValue(value, fieldName));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -378,7 +372,7 @@ public class IterUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将列表转成值为List的HashMap
|
||||
* 将列表转成值为List的Map集合
|
||||
*
|
||||
* @param resultMap 结果Map,可自定义结果Map类型
|
||||
* @param iterable 值列表
|
||||
@ -702,38 +696,40 @@ public class IterUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个{@link Iterable} 是否元素和顺序相同,返回{@code true}的条件是:
|
||||
* <p>判断两个{@link Iterable}中的元素与其顺序是否相同 <br>
|
||||
* 当满足下列情况时返回{@code true}:
|
||||
* <ul>
|
||||
* <li>两个{@link Iterable}必须长度相同</li>
|
||||
* <li>两个{@link Iterable}元素相同index的对象必须equals,满足{@link Objects#equals(Object, Object)}</li>
|
||||
* <li>两个{@link Iterable}都为{@code null};</li>
|
||||
* <li>两个{@link Iterable}满足{@code iterable1 == iterable2};</li>
|
||||
* <li>两个{@link Iterable}所有具有相同下标的元素皆满足{@link Objects#equals(Object, Object)};</li>
|
||||
* </ul>
|
||||
* 此方法来自Apache-Commons-Collections4。
|
||||
*
|
||||
* @param list1 列表1
|
||||
* @param list2 列表2
|
||||
* @param iterable1 列表1
|
||||
* @param iterable2 列表2
|
||||
* @return 是否相同
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static boolean isEqualList(final Iterable<?> list1, final Iterable<?> list2) {
|
||||
if (list1 == list2) {
|
||||
public static boolean isEqualList(final Iterable<?> iterable1, final Iterable<?> iterable2) {
|
||||
if (iterable1 == iterable2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Iterator<?> it1 = list1.iterator();
|
||||
final Iterator<?> it2 = list2.iterator();
|
||||
if (iterable1 == null || iterable2 == null) {
|
||||
return false;
|
||||
}
|
||||
final Iterator<?> iter1 = iterable1.iterator();
|
||||
final Iterator<?> iter2 = iterable2.iterator();
|
||||
Object obj1;
|
||||
Object obj2;
|
||||
while (it1.hasNext() && it2.hasNext()) {
|
||||
obj1 = it1.next();
|
||||
obj2 = it2.next();
|
||||
|
||||
while (iter1.hasNext() && iter2.hasNext()) {
|
||||
obj1 = iter1.next();
|
||||
obj2 = iter2.next();
|
||||
if (false == Objects.equals(obj1, obj2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 当两个Iterable长度不一致时返回false
|
||||
return false == (it1.hasNext() || it2.hasNext());
|
||||
return false == (iter1.hasNext() || iter2.hasNext());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,4 +15,5 @@ public interface IterableIter<T> extends Iterable<T>, Iterator<T> {
|
||||
default Iterator<T> iterator() {
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,6 +16,8 @@ public class IteratorEnumeration<E> implements Enumeration<E>, Serializable{
|
||||
|
||||
private final Iterator<E> iterator;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* @param iterator {@link Iterator}对象
|
||||
|
@ -1,11 +1,12 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import cn.hutool.core.collection.iter.IterableIter;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 分批迭代工具,可以分批处理数据
|
||||
@ -36,9 +37,11 @@ public class PartitionIter<T> implements IterableIter<List<T>>, Serializable {
|
||||
*
|
||||
* @param iterator 迭代器
|
||||
* @param partitionSize 每批大小,最后一批不满一批算一批
|
||||
* @throws IllegalArgumentException 当{@code partitionSize}小于等于0,或{@code iterator}为{@code null}时抛出
|
||||
*/
|
||||
public PartitionIter(final Iterator<T> iterator, final int partitionSize) {
|
||||
this.iterator = iterator;
|
||||
Assert.isTrue(partitionSize > 0, "partition size must greater than 0");
|
||||
this.iterator = Objects.requireNonNull(iterator);
|
||||
this.partitionSize = partitionSize;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package cn.hutool.core.collection.partition;
|
||||
|
||||
import cn.hutool.core.collection.partition.Partition;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -164,7 +164,7 @@ public class ZipWriter implements Closeable {
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public ZipWriter add(String path, final InputStream in) throws IORuntimeException {
|
||||
path = StrUtil.nullToEmpty(path);
|
||||
path = StrUtil.emptyIfNull(path);
|
||||
if (null == in) {
|
||||
// 空目录需要检查路径规范性,目录以"/"结尾
|
||||
path = StrUtil.addSuffixIfNot(path, StrUtil.SLASH);
|
||||
|
@ -783,11 +783,7 @@ public class DateTime extends Date {
|
||||
* @since 3.0.8
|
||||
*/
|
||||
public boolean isIn(final Date beginDate, final Date endDate) {
|
||||
final long beginMills = beginDate.getTime();
|
||||
final long endMills = endDate.getTime();
|
||||
final long thisMills = this.getTime();
|
||||
|
||||
return thisMills >= Math.min(beginMills, endMills) && thisMills <= Math.max(beginMills, endMills);
|
||||
return DateUtil.isIn(this, beginDate, endDate);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1381,11 +1381,49 @@ public class DateUtil extends CalendarUtil {
|
||||
* @since 3.0.8
|
||||
*/
|
||||
public static boolean isIn(final Date date, final Date beginDate, final Date endDate) {
|
||||
if (date instanceof DateTime) {
|
||||
return ((DateTime) date).isIn(beginDate, endDate);
|
||||
} else {
|
||||
return new DateTime(date).isIn(beginDate, endDate);
|
||||
return isIn(date, beginDate, endDate, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前日期是否在日期指定范围内<br>
|
||||
* 起始日期和结束日期可以互换<br>
|
||||
* 通过includeBegin, includeEnd参数控制日期范围区间是否为开区间,例如:传入参数:includeBegin=true, includeEnd=false,
|
||||
* 则本方法会判断 date ∈ (beginDate, endDate] 是否成立
|
||||
*
|
||||
* @param date 被检查的日期
|
||||
* @param beginDate 起始日期
|
||||
* @param endDate 结束日期
|
||||
* @param includeBegin 时间范围是否包含起始日期
|
||||
* @param includeEnd 时间范围是否包含结束日期
|
||||
* @return 是否在范围内
|
||||
* @author FengBaoheng
|
||||
* @since 5.8.6
|
||||
*/
|
||||
public static boolean isIn(final Date date, final Date beginDate, final Date endDate,
|
||||
final boolean includeBegin, final boolean includeEnd) {
|
||||
if (date == null || beginDate == null || endDate == null) {
|
||||
throw new IllegalArgumentException("参数不可为null");
|
||||
}
|
||||
|
||||
final long thisMills = date.getTime();
|
||||
final long beginMills = beginDate.getTime();
|
||||
final long endMills = endDate.getTime();
|
||||
final long rangeMin = Math.min(beginMills, endMills);
|
||||
final long rangeMax = Math.max(beginMills, endMills);
|
||||
|
||||
// 先判断是否满足 date ∈ (beginDate, endDate)
|
||||
boolean isIn = rangeMin < thisMills && thisMills < rangeMax;
|
||||
|
||||
// 若不满足,则再判断是否在时间范围的边界上
|
||||
if (false == isIn && includeBegin) {
|
||||
isIn = thisMills == rangeMin;
|
||||
}
|
||||
|
||||
if (false == isIn && includeEnd) {
|
||||
isIn = thisMills == rangeMax;
|
||||
}
|
||||
|
||||
return isIn;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,11 +181,49 @@ public class TemporalAccessorUtil extends TemporalUtil{
|
||||
* @param endDate 结束日期(包含)
|
||||
* @return 是否在范围内
|
||||
*/
|
||||
public static boolean isIn(TemporalAccessor date, TemporalAccessor beginDate, TemporalAccessor endDate){
|
||||
final long thisMills = TemporalAccessorUtil.toEpochMilli(date);
|
||||
final long beginMills = TemporalAccessorUtil.toEpochMilli(beginDate);
|
||||
final long endMills = TemporalAccessorUtil.toEpochMilli(endDate);
|
||||
public static boolean isIn(final TemporalAccessor date, final TemporalAccessor beginDate, final TemporalAccessor endDate){
|
||||
return isIn(date, beginDate, endDate, true, true);
|
||||
}
|
||||
|
||||
return thisMills >= Math.min(beginMills, endMills) && thisMills <= Math.max(beginMills, endMills);
|
||||
/**
|
||||
* 当前日期是否在日期指定范围内<br>
|
||||
* 起始日期和结束日期可以互换<br>
|
||||
* 通过includeBegin, includeEnd参数控制日期范围区间是否为开区间,例如:传入参数:includeBegin=true, includeEnd=false,
|
||||
* 则本方法会判断 date ∈ (beginDate, endDate] 是否成立
|
||||
*
|
||||
* @param date 被检查的日期
|
||||
* @param beginDate 起始日期
|
||||
* @param endDate 结束日期
|
||||
* @param includeBegin 时间范围是否包含起始日期
|
||||
* @param includeEnd 时间范围是否包含结束日期
|
||||
* @return 是否在范围内
|
||||
* @author FengBaoheng
|
||||
* @since 5.8.6
|
||||
*/
|
||||
public static boolean isIn(final TemporalAccessor date, final TemporalAccessor beginDate, final TemporalAccessor endDate,
|
||||
final boolean includeBegin, final boolean includeEnd) {
|
||||
if (date == null || beginDate == null || endDate == null) {
|
||||
throw new IllegalArgumentException("参数不可为null");
|
||||
}
|
||||
|
||||
final long thisMills = toEpochMilli(date);
|
||||
final long beginMills = toEpochMilli(beginDate);
|
||||
final long endMills = toEpochMilli(endDate);
|
||||
final long rangeMin = Math.min(beginMills, endMills);
|
||||
final long rangeMax = Math.max(beginMills, endMills);
|
||||
|
||||
// 先判断是否满足 date ∈ (beginDate, endDate)
|
||||
boolean isIn = rangeMin < thisMills && thisMills < rangeMax;
|
||||
|
||||
// 若不满足,则再判断是否在时间范围的边界上
|
||||
if (false == isIn && includeBegin) {
|
||||
isIn = thisMills == rangeMin;
|
||||
}
|
||||
|
||||
if (false == isIn && includeEnd) {
|
||||
isIn = thisMills == rangeMax;
|
||||
}
|
||||
|
||||
return isIn;
|
||||
}
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ public class ResourceUtil {
|
||||
* @return {@link URL}
|
||||
*/
|
||||
public static URL getResourceUrl(String resource, final Class<?> baseClass) {
|
||||
resource = StrUtil.nullToEmpty(resource);
|
||||
resource = StrUtil.emptyIfNull(resource);
|
||||
return (null != baseClass) ? baseClass.getResource(resource) : ClassLoaderUtil.getClassLoader().getResource(resource);
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ public class ClassScanner implements Serializable {
|
||||
* @param charset 编码
|
||||
*/
|
||||
public ClassScanner(String packageName, final Predicate<Class<?>> classPredicate, final Charset charset) {
|
||||
packageName = StrUtil.nullToEmpty(packageName);
|
||||
packageName = StrUtil.emptyIfNull(packageName);
|
||||
this.packageName = packageName;
|
||||
this.packageNameWithDot = StrUtil.addSuffixIfNot(packageName, StrUtil.DOT);
|
||||
this.packageDirName = packageName.replace(CharUtil.DOT, File.separatorChar);
|
||||
|
328
hutool-core/src/main/java/cn/hutool/core/map/MapGetUtil.java
Executable file
328
hutool-core/src/main/java/cn/hutool/core/map/MapGetUtil.java
Executable file
@ -0,0 +1,328 @@
|
||||
package cn.hutool.core.map;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.reflect.TypeReference;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Map的getXXX封装,提供针对通用型的value按照所需类型获取值
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class MapGetUtil {
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为字符串
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static String getStr(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为字符串
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static String getStr(final Map<?, ?> map, final Object key, final String defaultValue) {
|
||||
return get(map, key, String.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Integer
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Integer getInt(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Integer.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Integer
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Integer getInt(final Map<?, ?> map, final Object key, final Integer defaultValue) {
|
||||
return get(map, key, Integer.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Double
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Double getDouble(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Double.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Double
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Double getDouble(final Map<?, ?> map, final Object key, final Double defaultValue) {
|
||||
return get(map, key, Double.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Float
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Float getFloat(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Float.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Float
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Float getFloat(final Map<?, ?> map, final Object key, final Float defaultValue) {
|
||||
return get(map, key, Float.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Short
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Short getShort(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Short.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Short
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Short getShort(final Map<?, ?> map, final Object key, final Short defaultValue) {
|
||||
return get(map, key, Short.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Bool
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Boolean getBool(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Boolean.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Bool
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Boolean getBool(final Map<?, ?> map, final Object key, final Boolean defaultValue) {
|
||||
return get(map, key, Boolean.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Character
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Character getChar(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Character.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Character
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Character getChar(final Map<?, ?> map, final Object key, final Character defaultValue) {
|
||||
return get(map, key, Character.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Long
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Long getLong(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Long.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Long
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Long getLong(final Map<?, ?> map, final Object key, final Long defaultValue) {
|
||||
return get(map, key, Long.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为{@link Date}
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.1.2
|
||||
*/
|
||||
public static Date getDate(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Date.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为{@link Date}
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 4.1.2
|
||||
*/
|
||||
public static Date getDate(final Map<?, ?> map, final Object key, final Date defaultValue) {
|
||||
return get(map, key, Date.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为指定类型
|
||||
*
|
||||
* @param <T> 目标值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param type 值类型
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static <T> T get(final Map<?, ?> map, final Object key, final Class<T> type) {
|
||||
return get(map, key, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为指定类型
|
||||
*
|
||||
* @param <T> 目标值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param type 值类型
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static <T> T get(final Map<?, ?> map, final Object key, final Class<T> type, final T defaultValue) {
|
||||
return null == map ? defaultValue : Convert.convert(type, map.get(key), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为指定类型,此方法在转换失败后不抛异常,返回null。
|
||||
*
|
||||
* @param <T> 目标值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param type 值类型
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.5.3
|
||||
*/
|
||||
public static <T> T getQuietly(final Map<?, ?> map, final Object key, final Class<T> type, final T defaultValue) {
|
||||
return null == map ? defaultValue : Convert.convertQuietly(type, map.get(key), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为指定类型
|
||||
*
|
||||
* @param <T> 目标值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param type 值类型
|
||||
* @return 值
|
||||
* @since 4.5.12
|
||||
*/
|
||||
public static <T> T get(final Map<?, ?> map, final Object key, final TypeReference<T> type) {
|
||||
return get(map, key, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为指定类型
|
||||
*
|
||||
* @param <T> 目标值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param type 值类型
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static <T> T get(final Map<?, ?> map, final Object key, final TypeReference<T> type, final T defaultValue) {
|
||||
return null == map ? defaultValue : Convert.convert(type, map.get(key), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为指定类型,转换失败后返回null,不抛异常
|
||||
*
|
||||
* @param <T> 目标值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param type 值类型
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.5.3
|
||||
*/
|
||||
public static <T> T getQuietly(final Map<?, ?> map, final Object key, final TypeReference<T> type, final T defaultValue) {
|
||||
return null == map ? defaultValue : Convert.convertQuietly(type, map.get(key), defaultValue);
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@ import cn.hutool.core.collection.iter.IterUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
import cn.hutool.core.reflect.ConstructorUtil;
|
||||
import cn.hutool.core.reflect.TypeReference;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
@ -16,7 +15,6 @@ import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
@ -25,7 +23,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -41,7 +38,7 @@ import java.util.stream.Collectors;
|
||||
* @author Looly
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public class MapUtil {
|
||||
public class MapUtil extends MapGetUtil {
|
||||
|
||||
/**
|
||||
* 默认初始大小
|
||||
@ -250,9 +247,9 @@ public class MapUtil {
|
||||
if (null == mapType || mapType.isAssignableFrom(AbstractMap.class)) {
|
||||
return new HashMap<>();
|
||||
} else {
|
||||
try{
|
||||
try {
|
||||
return (Map<K, V>) ConstructorUtil.newInstance(mapType);
|
||||
}catch (UtilException e){
|
||||
} catch (final UtilException e) {
|
||||
// 不支持的map类型,返回默认的HashMap
|
||||
return new HashMap<>();
|
||||
}
|
||||
@ -483,14 +480,14 @@ public class MapUtil {
|
||||
}
|
||||
|
||||
final List<Map<K, V>> resultList = new ArrayList<>();
|
||||
for (Entry<K, ? extends Iterable<V>> entry : listMap.entrySet()) {
|
||||
for (final Entry<K, ? extends Iterable<V>> entry : listMap.entrySet()) {
|
||||
final Iterator<V> iterator = IterUtil.getIter(entry.getValue());
|
||||
if (IterUtil.isEmpty(iterator)) {
|
||||
continue;
|
||||
}
|
||||
final K key = entry.getKey();
|
||||
// 对已经存在的map添加元素
|
||||
for (Map<K, V> map : resultList) {
|
||||
for (final Map<K, V> map : resultList) {
|
||||
// 还可以继续添加元素
|
||||
if (iterator.hasNext()) {
|
||||
map.put(key, iterator.next());
|
||||
@ -966,319 +963,6 @@ public class MapUtil {
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为字符串
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static String getStr(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为字符串
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static String getStr(final Map<?, ?> map, final Object key, final String defaultValue) {
|
||||
return get(map, key, String.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Integer
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Integer getInt(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Integer.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Integer
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Integer getInt(final Map<?, ?> map, final Object key, final Integer defaultValue) {
|
||||
return get(map, key, Integer.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Double
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Double getDouble(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Double.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Double
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Double getDouble(final Map<?, ?> map, final Object key, final Double defaultValue) {
|
||||
return get(map, key, Double.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Float
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Float getFloat(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Float.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Float
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Float getFloat(final Map<?, ?> map, final Object key, final Float defaultValue) {
|
||||
return get(map, key, Float.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Short
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Short getShort(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Short.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Short
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Short getShort(final Map<?, ?> map, final Object key, final Short defaultValue) {
|
||||
return get(map, key, Short.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Bool
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Boolean getBool(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Boolean.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Bool
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Boolean getBool(final Map<?, ?> map, final Object key, final Boolean defaultValue) {
|
||||
return get(map, key, Boolean.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Character
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Character getChar(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Character.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Character
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Character getChar(final Map<?, ?> map, final Object key, final Character defaultValue) {
|
||||
return get(map, key, Character.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Long
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static Long getLong(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Long.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为Long
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static Long getLong(final Map<?, ?> map, final Object key, final Long defaultValue) {
|
||||
return get(map, key, Long.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为{@link Date}
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @return 值
|
||||
* @since 4.1.2
|
||||
*/
|
||||
public static Date getDate(final Map<?, ?> map, final Object key) {
|
||||
return get(map, key, Date.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为{@link Date}
|
||||
*
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 4.1.2
|
||||
*/
|
||||
public static Date getDate(final Map<?, ?> map, final Object key, final Date defaultValue) {
|
||||
return get(map, key, Date.class, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为指定类型
|
||||
*
|
||||
* @param <T> 目标值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param type 值类型
|
||||
* @return 值
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static <T> T get(final Map<?, ?> map, final Object key, final Class<T> type) {
|
||||
return get(map, key, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为指定类型
|
||||
*
|
||||
* @param <T> 目标值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param type 值类型
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static <T> T get(final Map<?, ?> map, final Object key, final Class<T> type, final T defaultValue) {
|
||||
return null == map ? defaultValue : Convert.convert(type, map.get(key), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为指定类型,此方法在转换失败后不抛异常,返回null。
|
||||
*
|
||||
* @param <T> 目标值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param type 值类型
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.5.3
|
||||
*/
|
||||
public static <T> T getQuietly(final Map<?, ?> map, final Object key, final Class<T> type, final T defaultValue) {
|
||||
return null == map ? defaultValue : Convert.convertQuietly(type, map.get(key), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为指定类型
|
||||
*
|
||||
* @param <T> 目标值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param type 值类型
|
||||
* @return 值
|
||||
* @since 4.5.12
|
||||
*/
|
||||
public static <T> T get(final Map<?, ?> map, final Object key, final TypeReference<T> type) {
|
||||
return get(map, key, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为指定类型
|
||||
*
|
||||
* @param <T> 目标值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param type 值类型
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public static <T> T get(final Map<?, ?> map, final Object key, final TypeReference<T> type, final T defaultValue) {
|
||||
return null == map ? defaultValue : Convert.convert(type, map.get(key), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map指定key的值,并转换为指定类型,转换失败后返回null,不抛异常
|
||||
*
|
||||
* @param <T> 目标值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param type 值类型
|
||||
* @param defaultValue 默认值
|
||||
* @return 值
|
||||
* @since 5.5.3
|
||||
*/
|
||||
public static <T> T getQuietly(final Map<?, ?> map, final Object key, final TypeReference<T> type, final T defaultValue) {
|
||||
return null == map ? defaultValue : Convert.convertQuietly(type, map.get(key), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重命名键<br>
|
||||
* 实现方式为一处然后重新put,当旧的key不存在直接返回<br>
|
||||
@ -1557,4 +1241,32 @@ public class MapUtil {
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据给定的entry列表,根据entry的key进行分组;
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param entries entry列表
|
||||
* @return entries
|
||||
* @since 5.8.6
|
||||
*/
|
||||
public static <K, V> Map<K, List<V>> grouping(final Iterable<Map.Entry<K, V>> entries) {
|
||||
if (CollUtil.isEmpty(entries)) {
|
||||
return zero();
|
||||
}
|
||||
|
||||
final Map<K, List<V>> map = new HashMap<>();
|
||||
for (final Map.Entry<K, V> pair : entries) {
|
||||
final List<V> values;
|
||||
if (map.containsKey(pair.getKey())) {
|
||||
values = map.get(pair.getKey());
|
||||
} else {
|
||||
values = ListUtil.of();
|
||||
map.put(pair.getKey(), values);
|
||||
}
|
||||
values.add(pair.getValue());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
@ -579,7 +579,7 @@ public class URLUtil {
|
||||
if (isEncodePath) {
|
||||
path = RFC3986.PATH.encode(path, CharsetUtil.UTF_8);
|
||||
}
|
||||
return protocol + domain + StrUtil.nullToEmpty(path) + StrUtil.nullToEmpty(params);
|
||||
return protocol + domain + StrUtil.emptyIfNull(path) + StrUtil.emptyIfNull(params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -406,7 +406,7 @@ public class UrlQuery {
|
||||
private void addParam(final String key, final String value, final Charset charset) {
|
||||
if (null != key) {
|
||||
final String actualKey = URLDecoder.decode(key, charset, isFormUrlEncoded);
|
||||
this.query.put(actualKey, StrUtil.nullToEmpty(URLDecoder.decode(value, charset, isFormUrlEncoded)));
|
||||
this.query.put(actualKey, StrUtil.emptyIfNull(URLDecoder.decode(value, charset, isFormUrlEncoded)));
|
||||
} else if (null != value) {
|
||||
// name为空,value作为name,value赋值null
|
||||
this.query.put(URLDecoder.decode(value, charset, isFormUrlEncoded), null);
|
||||
|
@ -26,7 +26,7 @@ public class CollectorUtil {
|
||||
* 说明已包含IDENTITY_FINISH特征 为 Characteristics.IDENTITY_FINISH 的缩写
|
||||
*/
|
||||
public static final Set<Collector.Characteristics> CH_ID
|
||||
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
|
||||
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
|
||||
/**
|
||||
* 说明不包含IDENTITY_FINISH特征
|
||||
*/
|
||||
@ -52,7 +52,7 @@ public class CollectorUtil {
|
||||
* @return {@link Collector}
|
||||
*/
|
||||
public static <T> Collector<T, ?, String> joining(final CharSequence delimiter,
|
||||
final Function<T, ? extends CharSequence> toStringFunc) {
|
||||
final Function<T, ? extends CharSequence> toStringFunc) {
|
||||
return joining(delimiter, StrUtil.EMPTY, StrUtil.EMPTY, toStringFunc);
|
||||
}
|
||||
|
||||
@ -67,15 +67,15 @@ public class CollectorUtil {
|
||||
* @return {@link Collector}
|
||||
*/
|
||||
public static <T> Collector<T, ?, String> joining(final CharSequence delimiter,
|
||||
final CharSequence prefix,
|
||||
final CharSequence suffix,
|
||||
final Function<T, ? extends CharSequence> toStringFunc) {
|
||||
final CharSequence prefix,
|
||||
final CharSequence suffix,
|
||||
final Function<T, ? extends CharSequence> toStringFunc) {
|
||||
return new SimpleCollector<>(
|
||||
() -> new StringJoiner(delimiter, prefix, suffix),
|
||||
(joiner, ele) -> joiner.add(toStringFunc.apply(ele)),
|
||||
StringJoiner::merge,
|
||||
StringJoiner::toString,
|
||||
Collections.emptySet()
|
||||
() -> new StringJoiner(delimiter, prefix, suffix),
|
||||
(joiner, ele) -> joiner.add(toStringFunc.apply(ele)),
|
||||
StringJoiner::merge,
|
||||
StringJoiner::toString,
|
||||
Collections.emptySet()
|
||||
);
|
||||
}
|
||||
|
||||
@ -94,8 +94,8 @@ public class CollectorUtil {
|
||||
* @return {@link Collector}
|
||||
*/
|
||||
public static <T, K, D, A, M extends Map<K, D>> Collector<T, ?, M> groupingBy(final Function<? super T, ? extends K> classifier,
|
||||
final Supplier<M> mapFactory,
|
||||
final Collector<? super T, A, D> downstream) {
|
||||
final Supplier<M> mapFactory,
|
||||
final Collector<? super T, A, D> downstream) {
|
||||
final Supplier<A> downstreamSupplier = downstream.supplier();
|
||||
final BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
|
||||
final BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
|
||||
@ -133,9 +133,8 @@ public class CollectorUtil {
|
||||
* @param <A> 下游操作在进行中间操作时对应类型
|
||||
* @return {@link Collector}
|
||||
*/
|
||||
public static <T, K, A, D>
|
||||
Collector<T, ?, Map<K, D>> groupingBy(final Function<? super T, ? extends K> classifier,
|
||||
final Collector<? super T, A, D> downstream) {
|
||||
public static <T, K, A, D> Collector<T, ?, Map<K, D>> groupingBy(final Function<? super T, ? extends K> classifier,
|
||||
final Collector<? super T, A, D> downstream) {
|
||||
return groupingBy(classifier, HashMap::new, downstream);
|
||||
}
|
||||
|
||||
@ -147,8 +146,7 @@ public class CollectorUtil {
|
||||
* @param <K> 实体中的分组依据对应类型,也是Map中key的类型
|
||||
* @return {@link Collector}
|
||||
*/
|
||||
public static <T, K> Collector<T, ?, Map<K, List<T>>>
|
||||
groupingBy(final Function<? super T, ? extends K> classifier) {
|
||||
public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(final Function<? super T, ? extends K> classifier) {
|
||||
return groupingBy(classifier, Collectors.toList());
|
||||
}
|
||||
|
||||
@ -163,10 +161,9 @@ public class CollectorUtil {
|
||||
* @param <U> map中value的类型
|
||||
* @return 对null友好的 toMap 操作的 {@link Collector}实现
|
||||
*/
|
||||
public static <T, K, U>
|
||||
Collector<T, ?, Map<K, U>> toMap(final Function<? super T, ? extends K> keyMapper,
|
||||
final Function<? super T, ? extends U> valueMapper,
|
||||
final BinaryOperator<U> mergeFunction) {
|
||||
public static <T, K, U> Collector<T, ?, Map<K, U>> toMap(final Function<? super T, ? extends K> keyMapper,
|
||||
final Function<? super T, ? extends U> valueMapper,
|
||||
final BinaryOperator<U> mergeFunction) {
|
||||
return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
|
||||
}
|
||||
|
||||
@ -185,11 +182,11 @@ public class CollectorUtil {
|
||||
*/
|
||||
public static <T, K, U, M extends Map<K, U>>
|
||||
Collector<T, ?, M> toMap(final Function<? super T, ? extends K> keyMapper,
|
||||
final Function<? super T, ? extends U> valueMapper,
|
||||
final BinaryOperator<U> mergeFunction,
|
||||
final Supplier<M> mapSupplier) {
|
||||
final Function<? super T, ? extends U> valueMapper,
|
||||
final BinaryOperator<U> mergeFunction,
|
||||
final Supplier<M> mapSupplier) {
|
||||
final BiConsumer<M, T> accumulator
|
||||
= (map, element) -> map.put(Opt.ofNullable(element).map(keyMapper).get(), Opt.ofNullable(element).map(valueMapper).get());
|
||||
= (map, element) -> map.put(Opt.ofNullable(element).map(keyMapper).get(), Opt.ofNullable(element).map(valueMapper).get());
|
||||
return new SimpleCollector<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
|
||||
}
|
||||
|
||||
@ -235,13 +232,13 @@ public class CollectorUtil {
|
||||
*/
|
||||
public static <K, V, R extends Map<K, List<V>>> Collector<Map<K, V>, ?, R> reduceListMap(final Supplier<R> mapSupplier) {
|
||||
return Collectors.reducing(mapSupplier.get(), value -> {
|
||||
R result = mapSupplier.get();
|
||||
value.forEach((k, v) -> result.computeIfAbsent(k, i -> new ArrayList<>()).add(v));
|
||||
return result;
|
||||
}, (l, r) -> {
|
||||
r.forEach((k, v) -> l.computeIfAbsent(k, i -> new ArrayList<>()).addAll(v));
|
||||
return l;
|
||||
}
|
||||
final R result = mapSupplier.get();
|
||||
value.forEach((k, v) -> result.computeIfAbsent(k, i -> new ArrayList<>()).add(v));
|
||||
return result;
|
||||
}, (l, r) -> {
|
||||
r.forEach((k, v) -> l.computeIfAbsent(k, i -> new ArrayList<>()).addAll(v));
|
||||
return l;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@ -271,7 +268,7 @@ public class CollectorUtil {
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static <T, K, V> Collector<T, List<T>, EntryStream<K, V>> toEntryStream(
|
||||
Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends V> valueMapper) {
|
||||
final Function<? super T, ? extends K> keyMapper, final Function<? super T, ? extends V> valueMapper) {
|
||||
Objects.requireNonNull(keyMapper);
|
||||
Objects.requireNonNull(valueMapper);
|
||||
return transform(ArrayList::new, list -> EntryStream.of(list, keyMapper, valueMapper));
|
||||
@ -306,11 +303,14 @@ public class CollectorUtil {
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static <T, R, C extends Collection<T>> Collector<T, C, R> transform(
|
||||
Supplier<C> collFactory, Function<C, R> mapper) {
|
||||
final Supplier<C> collFactory, final Function<C, R> mapper) {
|
||||
Objects.requireNonNull(collFactory);
|
||||
Objects.requireNonNull(mapper);
|
||||
return new SimpleCollector<>(
|
||||
collFactory, C::add, (l1, l2) -> { l1.addAll(l2); return l1; }, mapper, CH_NOID
|
||||
collFactory, C::add, (l1, l2) -> {
|
||||
l1.addAll(l2);
|
||||
return l1;
|
||||
}, mapper, CH_NOID
|
||||
);
|
||||
}
|
||||
|
||||
@ -329,7 +329,7 @@ public class CollectorUtil {
|
||||
* @return 收集器
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static <T, R> Collector<T, List<T>, R> transform(Function<List<T>, R> mapper) {
|
||||
public static <T, R> Collector<T, List<T>, R> transform(final Function<List<T>, R> mapper) {
|
||||
return transform(ArrayList::new, mapper);
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ public class CharSequenceUtil extends StrChecker {
|
||||
* @param str 被转换的字符串
|
||||
* @return 转换后的字符串
|
||||
*/
|
||||
public static String nullToEmpty(final CharSequence str) {
|
||||
public static String emptyIfNull(final CharSequence str) {
|
||||
return ObjUtil.defaultIfNull(str, EMPTY).toString();
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ public class CharSequenceUtil extends StrChecker {
|
||||
* @param str 被转换的字符串
|
||||
* @return 转换后的字符串
|
||||
*/
|
||||
public static <T extends CharSequence> T emptyToNull(final T str) {
|
||||
public static <T extends CharSequence> T nullIfEmpty(final T str) {
|
||||
return isEmpty(str) ? null : str;
|
||||
}
|
||||
|
||||
@ -809,10 +809,10 @@ public class CharSequenceUtil extends StrChecker {
|
||||
/**
|
||||
* 指定范围内查找指定字符
|
||||
*
|
||||
* @param text 字符串
|
||||
* @param matcher 被查找的字符匹配器
|
||||
* @param start 起始位置,如果小于0,从0开始查找
|
||||
* @param end 终止位置,如果超过str.length()则默认查找到字符串末尾
|
||||
* @param text 字符串
|
||||
* @param matcher 被查找的字符匹配器
|
||||
* @param start 起始位置,如果小于0,从0开始查找
|
||||
* @param end 终止位置,如果超过str.length()则默认查找到字符串末尾
|
||||
* @return 位置
|
||||
* @since 6.0.0
|
||||
*/
|
||||
@ -2521,7 +2521,7 @@ public class CharSequenceUtil extends StrChecker {
|
||||
* @return 包装后的字符串
|
||||
*/
|
||||
public static String wrap(final CharSequence str, final CharSequence prefix, final CharSequence suffix) {
|
||||
return nullToEmpty(prefix).concat(nullToEmpty(str)).concat(nullToEmpty(suffix));
|
||||
return emptyIfNull(prefix).concat(emptyIfNull(str)).concat(emptyIfNull(suffix));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3990,7 +3990,7 @@ public class CharSequenceUtil extends StrChecker {
|
||||
public static String concat(final boolean isNullToEmpty, final CharSequence... strs) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (final CharSequence str : strs) {
|
||||
sb.append(isNullToEmpty ? nullToEmpty(str) : str);
|
||||
sb.append(isNullToEmpty ? emptyIfNull(str) : str);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.hutool.core.thread;
|
||||
|
||||
import cn.hutool.core.util.RuntimeUtil;
|
||||
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletionService;
|
||||
@ -129,7 +131,7 @@ public class ThreadUtil {
|
||||
}
|
||||
|
||||
// 最佳的线程数 = CPU可用核心数 / (1 - 阻塞系数)
|
||||
final int poolSize = (int) (Runtime.getRuntime().availableProcessors() / (1 - blockingCoefficient));
|
||||
final int poolSize = (int) (RuntimeUtil.getProcessorCount() / (1 - blockingCoefficient));
|
||||
return ExecutorBuilder.of().setCorePoolSize(poolSize).setMaxPoolSize(poolSize).setKeepAliveTime(0L).build();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.hutool.core.util;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.iter.IterUtil;
|
||||
import cn.hutool.core.comparator.CompareUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
@ -9,15 +10,13 @@ import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.math.NumberUtil;
|
||||
import cn.hutool.core.reflect.ClassUtil;
|
||||
import cn.hutool.core.reflect.MethodUtil;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Array;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@ -29,13 +28,12 @@ import java.util.function.Supplier;
|
||||
public class ObjUtil {
|
||||
|
||||
/**
|
||||
* 比较两个对象是否相等。
|
||||
* 相同的条件有两个,满足其一即可:<br>
|
||||
* <ol>
|
||||
* <li>obj1 == null && obj2 == null</li>
|
||||
* <li>obj1.equals(obj2)</li>
|
||||
* <li>如果是BigDecimal比较,0 == obj1.compareTo(obj2)</li>
|
||||
* </ol>
|
||||
* <p>比较两个对象是否相等,满足下述任意条件即返回{@code true}:
|
||||
* <ul>
|
||||
* <li>若两对象皆为{@link BigDecimal},且满足{@code 0 == obj1.compareTo(obj2)}</li>
|
||||
* <li>{@code obj1 == null && obj2 == null}</li>
|
||||
* <li>{@code obj1.equals(obj2)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj1 对象1
|
||||
* @param obj2 对象2
|
||||
@ -50,27 +48,27 @@ public class ObjUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两个对象是否不相等。<br>
|
||||
* 比较两个对象是否不相等
|
||||
*
|
||||
* @param obj1 对象1
|
||||
* @param obj2 对象2
|
||||
* @return 是否不等
|
||||
* @since 3.0.7
|
||||
* @see #equals(Object, Object)
|
||||
*/
|
||||
public static boolean notEquals(final Object obj1, final Object obj2) {
|
||||
return false == equals(obj1, obj2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算对象长度,如果是字符串调用其length函数,集合类调用其size函数,数组调用其length属性,其他可遍历对象遍历计算长度<br>
|
||||
* 支持的类型包括:
|
||||
* <p>计算对象长度,支持类型包括:
|
||||
* <ul>
|
||||
* <li>CharSequence</li>
|
||||
* <li>Map</li>
|
||||
* <li>Iterator</li>
|
||||
* <li>Iterable</li>
|
||||
* <li>Enumeration</li>
|
||||
* <li>Array</li>
|
||||
* <li>{@code null}:默认返回{@code 0};</li>
|
||||
* <li>数组:返回数组长度;</li>
|
||||
* <li>{@link CharSequence}:返回{@link CharSequence#length()};</li>
|
||||
* <li>{@link Collection}:返回{@link Collection#size()};</li>
|
||||
* <li>{@link Iterator}或{@link Iterable}:可迭代的元素数量;</li>
|
||||
* <li>{@link Enumeration}:返回可迭代的元素数量;</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 被计算长度的对象
|
||||
@ -100,6 +98,9 @@ public class ObjUtil {
|
||||
}
|
||||
return count;
|
||||
}
|
||||
if (obj.getClass().isArray()) {
|
||||
return Array.getLength(obj);
|
||||
}
|
||||
if (obj instanceof Enumeration) {
|
||||
final Enumeration<?> enumeration = (Enumeration<?>) obj;
|
||||
count = 0;
|
||||
@ -109,23 +110,21 @@ public class ObjUtil {
|
||||
}
|
||||
return count;
|
||||
}
|
||||
if (obj.getClass().isArray()) {
|
||||
return Array.getLength(obj);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象中是否包含元素<br>
|
||||
* 支持的对象类型包括:
|
||||
* <p>检查{@code obj}中是否包含{@code element},若{@code obj}为{@code null},则直接返回{@code false}。<br>
|
||||
* 支持类型包括:
|
||||
* <ul>
|
||||
* <li>String</li>
|
||||
* <li>Collection</li>
|
||||
* <li>Map</li>
|
||||
* <li>Iterator</li>
|
||||
* <li>Iterable</li>
|
||||
* <li>Enumeration</li>
|
||||
* <li>Array</li>
|
||||
* <li>{@code null}:默认返回{@code false};</li>
|
||||
* <li>{@link String}:等同{@link String#contains(CharSequence)};</li>
|
||||
* <li>{@link Collection}:等同{@link Collection#contains(Object)};</li>
|
||||
* <li>{@link Map}:等同{@link Map#containsValue(Object)};</li>
|
||||
* <li>
|
||||
* {@link Iterator}、{@link Iterable}、{@link Enumeration}或数组:
|
||||
* 等同于遍历后对其元素调用{@link #equals(Object, Object)}方法;
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 对象
|
||||
@ -182,12 +181,7 @@ public class ObjUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查对象是否为null<br>
|
||||
* 判断标准为:
|
||||
*
|
||||
* <pre>
|
||||
* 1. == null
|
||||
* </pre>
|
||||
* 检查对象是否为{@code null}
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return 是否为null
|
||||
@ -197,7 +191,7 @@ public class ObjUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查对象是否不为null
|
||||
* 检查对象是否不为{@code null}
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return 是否为null
|
||||
@ -207,19 +201,26 @@ public class ObjUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断指定对象是否为空,支持:
|
||||
*
|
||||
* <pre>
|
||||
* 1. CharSequence
|
||||
* 2. Map
|
||||
* 3. Iterable
|
||||
* 4. Iterator
|
||||
* 5. Array
|
||||
* </pre>
|
||||
* 判断指定对象是否为空,支持类型包括:
|
||||
* <ul>
|
||||
* <li>{@code null}:默认返回{@code true};</li>
|
||||
* <li>数组:等同于{@link ArrayUtil#isEmpty(Object)};</li>
|
||||
* <li>{@link CharSequence}:等同于{@link CharSequenceUtil#isEmpty(CharSequence)};</li>
|
||||
* <li>{@link Collection}:等同于{@link CollUtil#isEmpty(Collection)};</li>
|
||||
* <li>{@link Map}:等同于{@link MapUtil#isEmpty(Map)};</li>
|
||||
* <li>
|
||||
* {@link Iterator}或{@link Iterable}:等同于{@link IterUtil#isEmpty(Iterator)}、
|
||||
* {@link IterUtil#isEmpty(Iterable)};
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 被判断的对象
|
||||
* @return 是否为空,如果类型不支持,返回false
|
||||
* @since 4.5.7
|
||||
* @see StrUtil#isEmpty(CharSequence)
|
||||
* @see MapUtil#isEmpty(Map)
|
||||
* @see IterUtil#isEmpty(Iterable)
|
||||
* @see IterUtil#isEmpty(Iterator)
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static boolean isEmpty(final Object obj) {
|
||||
@ -229,7 +230,9 @@ public class ObjUtil {
|
||||
|
||||
if (obj instanceof CharSequence) {
|
||||
return StrUtil.isEmpty((CharSequence) obj);
|
||||
} else if (obj instanceof Map) {
|
||||
} else if(obj instanceof Collection){
|
||||
return CollUtil.isEmpty((Collection)obj);
|
||||
}else if (obj instanceof Map) {
|
||||
return MapUtil.isEmpty((Map) obj);
|
||||
} else if (obj instanceof Iterable) {
|
||||
return IterUtil.isEmpty((Iterable) obj);
|
||||
@ -243,34 +246,26 @@ public class ObjUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断指定对象是否为非空,支持:
|
||||
*
|
||||
* <pre>
|
||||
* 1. CharSequence
|
||||
* 2. Map
|
||||
* 3. Iterable
|
||||
* 4. Iterator
|
||||
* 5. Array
|
||||
* </pre>
|
||||
* 判断指定对象是否为非空
|
||||
*
|
||||
* @param obj 被判断的对象
|
||||
* @return 是否为空,如果类型不支持,返回true
|
||||
* @since 4.5.7
|
||||
* @see #isEmpty(Object)
|
||||
*/
|
||||
public static boolean isNotEmpty(final Object obj) {
|
||||
return false == isEmpty(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果给定对象为{@code null}返回默认值
|
||||
*
|
||||
* <pre>
|
||||
* ObjectUtil.defaultIfNull(null, null) = null
|
||||
* ObjectUtil.defaultIfNull(null, "") = ""
|
||||
* ObjectUtil.defaultIfNull(null, "zz") = "zz"
|
||||
* ObjectUtil.defaultIfNull("abc", *) = "abc"
|
||||
* ObjectUtil.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
|
||||
* </pre>
|
||||
* <p>如果给定对象为{@code null}返回默认值
|
||||
* <pre>{@code
|
||||
* ObjectUtil.defaultIfNull(null, null); // = null
|
||||
* ObjectUtil.defaultIfNull(null, ""); // = ""
|
||||
* ObjectUtil.defaultIfNull(null, "zz"); // = "zz"
|
||||
* ObjectUtil.defaultIfNull("abc", *); // = "abc"
|
||||
* ObjectUtil.defaultIfNull(Boolean.TRUE, *); // = Boolean.TRUE
|
||||
* }</pre>
|
||||
*
|
||||
* @param <T> 对象类型
|
||||
* @param object 被检查对象,可能为{@code null}
|
||||
@ -333,14 +328,20 @@ public class ObjUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 克隆对象<br>
|
||||
* 如果对象实现Cloneable接口,调用其clone方法<br>
|
||||
* 如果实现Serializable接口,执行深度克隆<br>
|
||||
* 否则返回{@code null}
|
||||
* <p>克隆对象
|
||||
* <ol>
|
||||
* <li>如果对象是数组,则等同于{@link ArrayUtil#clone(Object)};</li>
|
||||
* <li>如果对象实现了{@link Cloneable}接口,调用其{@code Cloneable#clone()}方法;</li>
|
||||
* <li>如果对象实现了{@link Serializable}接口,执行深度克隆;</li>
|
||||
* <li>不符合上述任意情况则返回{@code null};</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param <T> 对象类型
|
||||
* @param obj 被克隆对象
|
||||
* @return 克隆后的对象
|
||||
* @see ArrayUtil#clone(Object)
|
||||
* @see Object#clone()
|
||||
* @see #cloneByStream(Object)
|
||||
*/
|
||||
public static <T> T clone(final T obj) {
|
||||
T result = ArrayUtil.clone(obj);
|
||||
@ -360,6 +361,7 @@ public class ObjUtil {
|
||||
* @param <T> 对象类型
|
||||
* @param obj 对象
|
||||
* @return 克隆后或原对象
|
||||
* @see #clone(Object)
|
||||
*/
|
||||
public static <T> T cloneIfPossible(final T obj) {
|
||||
T clone = null;
|
||||
@ -373,12 +375,13 @@ public class ObjUtil {
|
||||
|
||||
/**
|
||||
* 序列化后拷贝流的方式克隆<br>
|
||||
* 对象必须实现Serializable接口
|
||||
* 若对象未实现{@link Serializable}接口则默认返回{@code null}
|
||||
*
|
||||
* @param <T> 对象类型
|
||||
* @param obj 被克隆对象
|
||||
* @return 克隆后的对象
|
||||
* @throws UtilException IO异常和ClassNotFoundException封装
|
||||
* @see SerializeUtil#clone(Object)
|
||||
*/
|
||||
public static <T> T cloneByStream(final T obj) {
|
||||
return SerializeUtil.clone(obj);
|
||||
@ -399,12 +402,15 @@ public class ObjUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为有效的数字<br>
|
||||
* 检查Double和Float是否为无限大,或者Not a Number<br>
|
||||
* 非数字类型和Null将返回true
|
||||
* 检查是否为有效的数字,若对象不为{@link Number},则直接返回{@code true},否则:
|
||||
* <ul>
|
||||
* <li>若对象类型为{@link Double},则检查{@link Double#isInfinite()}或{@link Double#isNaN()};</li>
|
||||
* <li>若对象类型为{@link Float},则检查{@link Float#isInfinite()}或{@link Float#isNaN()};</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 被检查类型
|
||||
* @return 检查结果,非数字类型和Null将返回true
|
||||
* @see NumberUtil#isValidNumber(Number)
|
||||
*/
|
||||
public static boolean isValidIfNumber(final Object obj) {
|
||||
if (obj instanceof Number) {
|
||||
@ -454,7 +460,7 @@ public class ObjUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得给定类的第一个泛型参数
|
||||
* 获得给定类指定下标的泛型参数
|
||||
*
|
||||
* @param obj 被检查的对象
|
||||
* @param index 泛型类型的索引号,即第几个泛型类型
|
||||
@ -466,16 +472,17 @@ public class ObjUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Object转为String<br>
|
||||
* 策略为:
|
||||
* <pre>
|
||||
* 1、null转为"null"
|
||||
* 2、调用Convert.toStr(Object)转换
|
||||
* </pre>
|
||||
* <p>将对象转为字符串
|
||||
* <ul>
|
||||
* <li>若对象为{@code null},则返回“null”;</li>
|
||||
* <li>若对象为{@link Map},则返回{@code Map#toString()};</li>
|
||||
* <li>若对象为其他类型,则调用{@link Convert#toStr(Object)}进行转换;</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj Bean对象
|
||||
* @return Bean所有字段转为Map后的字符串
|
||||
* @return 转换后的字符串
|
||||
* @since 3.2.0
|
||||
* @see Convert#toStr(Object)
|
||||
*/
|
||||
public static String toString(final Object obj) {
|
||||
if (null == obj) {
|
||||
@ -484,7 +491,6 @@ public class ObjUtil {
|
||||
if (obj instanceof Map) {
|
||||
return obj.toString();
|
||||
}
|
||||
|
||||
return Convert.toStr(obj);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* 系统运行时工具类,用于执行系统命令的工具
|
||||
@ -234,11 +235,21 @@ public class RuntimeUtil {
|
||||
/**
|
||||
* 获得JVM可用的处理器数量(一般为CPU核心数)
|
||||
*
|
||||
* <p>
|
||||
* 这里做一个特殊的处理,在特殊的CPU上面,会有获取不到CPU数量的情况,所以这里做一个保护;
|
||||
* 默认给一个7,真实的CPU基本都是偶数,方便区分。
|
||||
* 如果不做处理,会出现创建线程池时{@link ThreadPoolExecutor},抛出异常:{@link IllegalArgumentException}
|
||||
*</p>
|
||||
*
|
||||
* @return 可用的处理器数量
|
||||
* @since 5.3.0
|
||||
*/
|
||||
public static int getProcessorCount() {
|
||||
return Runtime.getRuntime().availableProcessors();
|
||||
int cpu = Runtime.getRuntime().availableProcessors();
|
||||
if (cpu <= 0) {
|
||||
cpu = 7;
|
||||
}
|
||||
return cpu;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,50 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* test for {@link ArrayIter}
|
||||
*/
|
||||
public class ArrayIterTest {
|
||||
|
||||
@Test
|
||||
public void testHasNext() {
|
||||
Integer[] arr = new Integer[]{ 1, 2, 3 };
|
||||
ArrayIter<Integer> iter = new ArrayIter<>(arr);
|
||||
Assert.assertTrue(iter.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNext() {
|
||||
Integer[] arr = new Integer[]{ 1, 2, 3 };
|
||||
ArrayIter<Integer> iter = new ArrayIter<>(arr);
|
||||
Assert.assertEquals((Integer)1, iter.next());
|
||||
Assert.assertEquals((Integer)2, iter.next());
|
||||
Assert.assertEquals((Integer)3, iter.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove() {
|
||||
Integer[] arr = new Integer[]{ 1, 2, 3 };
|
||||
ArrayIter<Integer> iter = new ArrayIter<>(arr);
|
||||
Assert.assertThrows(UnsupportedOperationException.class, iter::remove);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetArray() {
|
||||
Integer[] arr = new Integer[]{ 1, 2, 3 };
|
||||
ArrayIter<Integer> iter = new ArrayIter<>(arr);
|
||||
Assert.assertEquals(arr, iter.getArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReset() {
|
||||
Integer[] arr = new Integer[]{ 1, 2, 3 };
|
||||
ArrayIter<Integer> iter = new ArrayIter<>(arr);
|
||||
Assert.assertEquals((Integer)1, iter.next());
|
||||
iter.reset();
|
||||
Assert.assertEquals((Integer)1, iter.next());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* test for {@link CopiedIter}
|
||||
*/
|
||||
public class CopiedIterTest {
|
||||
|
||||
@Test
|
||||
public void copyOf() {
|
||||
List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
Iterator<Integer> iter = list.iterator();
|
||||
Assert.assertEquals((Integer)1, iter.next());
|
||||
|
||||
Assert.assertEquals((Integer)2, CopiedIter.copyOf(iter).next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasNext() {
|
||||
Assert.assertTrue(CopiedIter.copyOf(Arrays.asList(1, 2, 3).iterator()).hasNext());
|
||||
Assert.assertFalse(CopiedIter.copyOf(Collections.emptyIterator()).hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void next() {
|
||||
List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
Iterator<Integer> iter = CopiedIter.copyOf(list.iterator());
|
||||
Assert.assertEquals((Integer)1, iter.next());
|
||||
Assert.assertEquals((Integer)2, iter.next());
|
||||
Assert.assertEquals((Integer)3, iter.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void remove() {
|
||||
List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
Iterator<Integer> iter = CopiedIter.copyOf(list.iterator());
|
||||
Assert.assertThrows(UnsupportedOperationException.class, iter::remove);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* @author huangchengxing
|
||||
*/
|
||||
public class EnumerationIterTest {
|
||||
|
||||
@Test
|
||||
public void testHasNext() {
|
||||
Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
|
||||
EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
|
||||
Assert.assertTrue(iter.hasNext());
|
||||
Assert.assertFalse(new EnumerationIter<>(new IteratorEnumeration<>(Collections.emptyIterator())).hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNext() {
|
||||
Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
|
||||
EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
|
||||
Assert.assertEquals((Integer)1, iter.next());
|
||||
Assert.assertEquals((Integer)2, iter.next());
|
||||
Assert.assertEquals((Integer)3, iter.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove() {
|
||||
Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
|
||||
EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
|
||||
Assert.assertThrows(UnsupportedOperationException.class, iter::remove);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator() {
|
||||
Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
|
||||
EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
|
||||
Assert.assertSame(iter, iter.iterator());
|
||||
}
|
||||
|
||||
}
|
@ -4,7 +4,10 @@ import cn.hutool.core.collection.ListUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class FilterIterTest {
|
||||
|
||||
@ -20,4 +23,40 @@ public class FilterIterTest {
|
||||
}
|
||||
Assert.assertEquals(2, count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasNext() {
|
||||
Iterator<Integer> iter = new FilterIter<>(Arrays.asList(1, 2, 3).iterator(), i -> true);
|
||||
Assert.assertTrue(iter.hasNext());
|
||||
iter = new FilterIter<>(Collections.emptyIterator(), i -> true);
|
||||
Assert.assertFalse(iter.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void next() {
|
||||
// 只保留奇数
|
||||
Iterator<Integer> iter = new FilterIter<>(Arrays.asList(1, 2, 3).iterator(), i -> (i & 1) == 1);
|
||||
Assert.assertEquals((Integer)1, iter.next());
|
||||
Assert.assertEquals((Integer)3, iter.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void remove() {
|
||||
Iterator<Integer> iter = new FilterIter<>(Collections.emptyIterator(), i -> true);
|
||||
Assert.assertThrows(IllegalStateException.class, iter::remove);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIterator() {
|
||||
FilterIter<Integer> iter = new FilterIter<>(Collections.emptyIterator(), i -> true);
|
||||
Assert.assertSame(Collections.emptyIterator(), iter.getIterator());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFilter() {
|
||||
Predicate<Integer> predicate = i -> true;
|
||||
FilterIter<Integer> iter = new FilterIter<>(Collections.emptyIterator(), predicate);
|
||||
Assert.assertSame(predicate, iter.getFilter());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* test for {@link IterChain}
|
||||
*/
|
||||
public class IterChainTest {
|
||||
|
||||
@Test
|
||||
public void testAddChain() {
|
||||
Iterator<Integer> iter1 = Arrays.asList(1, 2).iterator();
|
||||
Iterator<Integer> iter2 = Arrays.asList(3, 4).iterator();
|
||||
IterChain<Integer> iterChain = new IterChain<>();
|
||||
Assert.assertSame(iterChain, iterChain.addChain(iter1));
|
||||
Assert.assertSame(iterChain, iterChain.addChain(iter2));
|
||||
Assert.assertEquals(2, iterChain.allIterators.size());
|
||||
|
||||
iterChain = new IterChain<>(iter1, iter2);
|
||||
Assert.assertEquals(2, iterChain.allIterators.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasNext() {
|
||||
IterChain<Integer> iterChain = new IterChain<>();
|
||||
Assert.assertFalse(iterChain.hasNext());
|
||||
Assert.assertFalse(iterChain.addChain(Collections.emptyIterator()).hasNext());
|
||||
Assert.assertTrue(iterChain.addChain(Arrays.asList(3, 4).iterator()).hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNext() {
|
||||
Iterator<Integer> iter1 = Arrays.asList(1, 2).iterator();
|
||||
Iterator<Integer> iter2 = Arrays.asList(3, 4).iterator();
|
||||
IterChain<Integer> iterChain = new IterChain<>();
|
||||
Assert.assertSame(iterChain, iterChain.addChain(iter1));
|
||||
Assert.assertSame(iterChain, iterChain.addChain(iter2));
|
||||
Assert.assertEquals((Integer)1, iterChain.next());
|
||||
Assert.assertEquals((Integer)2, iterChain.next());
|
||||
Assert.assertEquals((Integer)3, iterChain.next());
|
||||
Assert.assertEquals((Integer)4, iterChain.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove() {
|
||||
IterChain<Integer> iterChain = new IterChain<>();
|
||||
iterChain.addChain(Arrays.asList(1, 2).iterator());
|
||||
Assert.assertThrows(IllegalStateException.class, iterChain::remove);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator() {
|
||||
Iterator<Integer> iter1 = Arrays.asList(1, 2).iterator();
|
||||
Iterator<Integer> iter2 = Arrays.asList(3, 4).iterator();
|
||||
IterChain<Integer> iterChain = new IterChain<>();
|
||||
Assert.assertSame(iterChain, iterChain.addChain(iter1));
|
||||
Assert.assertSame(iterChain, iterChain.addChain(iter2));
|
||||
|
||||
Iterator<Iterator<Integer>> iterators = iterChain.iterator();
|
||||
Assert.assertSame(iter1, iterators.next());
|
||||
Assert.assertSame(iter2, iterators.next());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,306 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* test for {@link IterUtil}
|
||||
*/
|
||||
public class IterUtilTest {
|
||||
|
||||
@Test
|
||||
public void testGetIter() {
|
||||
Assert.assertNull(IterUtil.getIter(null));
|
||||
Assert.assertEquals(Collections.emptyIterator(), IterUtil.getIter(Collections.emptyList()));
|
||||
|
||||
Assert.assertNull(IterUtil.getIter((Object)null));
|
||||
Assert.assertNotNull(IterUtil.getIter(Collections.emptyIterator()));
|
||||
Assert.assertNotNull(IterUtil.getIter((Object)Collections.emptyList()));
|
||||
Assert.assertNotNull(IterUtil.getIter(new Integer[0]));
|
||||
Assert.assertNotNull(IterUtil.getIter(Collections.emptyMap()));
|
||||
Assert.assertNull(IterUtil.getIter((NodeList)null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEmpty() {
|
||||
Assert.assertTrue(IterUtil.isEmpty(Collections.emptyIterator()));
|
||||
Assert.assertFalse(IterUtil.isEmpty(Arrays.asList(1, 2).iterator()));
|
||||
|
||||
Assert.assertTrue(IterUtil.isEmpty(Collections.emptyList()));
|
||||
Assert.assertFalse(IterUtil.isEmpty(Arrays.asList(1, 2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsNotEmpty() {
|
||||
Assert.assertFalse(IterUtil.isNotEmpty(Collections.emptyIterator()));
|
||||
Assert.assertTrue(IterUtil.isNotEmpty(Arrays.asList(1, 2).iterator()));
|
||||
|
||||
Assert.assertFalse(IterUtil.isNotEmpty(Collections.emptyList()));
|
||||
Assert.assertTrue(IterUtil.isNotEmpty(Arrays.asList(1, 2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasNull() {
|
||||
Assert.assertFalse(IterUtil.hasNull(Arrays.asList(1, 3, 2).iterator()));
|
||||
Assert.assertTrue(IterUtil.hasNull(Arrays.asList(1, null, 2).iterator()));
|
||||
Assert.assertFalse(IterUtil.hasNull(Collections.emptyIterator()));
|
||||
Assert.assertTrue(IterUtil.hasNull(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAllNull() {
|
||||
Assert.assertTrue(IterUtil.isAllNull(Arrays.asList(null, null)));
|
||||
Assert.assertFalse(IterUtil.isAllNull(Arrays.asList(1, null)));
|
||||
Assert.assertTrue(IterUtil.isAllNull((Iterable<?>)null));
|
||||
Assert.assertTrue(IterUtil.isAllNull(Arrays.asList(null, null).iterator()));
|
||||
Assert.assertFalse(IterUtil.isAllNull(Arrays.asList(1, null).iterator()));
|
||||
Assert.assertTrue(IterUtil.isAllNull((Iterator<?>)null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountMap() {
|
||||
Object o1 = new Object();
|
||||
Object o2 = new Object();
|
||||
Map<Object, Integer> countMap = IterUtil.countMap(Arrays.asList(o1, o2, o1, o1).iterator());
|
||||
Assert.assertEquals((Integer)3, countMap.get(o1));
|
||||
Assert.assertEquals((Integer)1, countMap.get(o2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldValueMap() {
|
||||
Bean bean1 = new Bean(1, "A");
|
||||
Bean bean2 = new Bean(2, "B");
|
||||
Map<Integer, Bean> map = IterUtil.fieldValueMap(Arrays.asList(bean1, bean2).iterator(), "id");
|
||||
Assert.assertEquals(bean1, map.get(1));
|
||||
Assert.assertEquals(bean2, map.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldValueAsMap() {
|
||||
Bean bean1 = new Bean(1, "A");
|
||||
Bean bean2 = new Bean(2, "B");
|
||||
Map<Integer, String> map = IterUtil.fieldValueAsMap(
|
||||
Arrays.asList(bean1, bean2).iterator(), "id", "name"
|
||||
);
|
||||
Assert.assertEquals("A", map.get(1));
|
||||
Assert.assertEquals("B", map.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldValueList() {
|
||||
Bean bean1 = new Bean(1, "A");
|
||||
Bean bean2 = new Bean(2, "B");
|
||||
Assert.assertEquals(Arrays.asList(1, 2), IterUtil.fieldValueList(Arrays.asList(bean1, bean2), "id"));
|
||||
Assert.assertEquals(
|
||||
Arrays.asList(1, 2),
|
||||
IterUtil.fieldValueList(Arrays.asList(bean1, bean2).iterator(), "id")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoin() {
|
||||
List<String> stringList = Arrays.asList("1", "2", "3");
|
||||
Assert.assertEquals("123", IterUtil.join(stringList.iterator(), ""));
|
||||
Assert.assertEquals("-1--2--3-", IterUtil.join(stringList.iterator(), "", "-", "-"));
|
||||
Assert.assertEquals("123", IterUtil.join(stringList.iterator(), "", Function.identity()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToMap() {
|
||||
List<Integer> keys = Arrays.asList(1, 2, 3);
|
||||
|
||||
Map<Integer, Integer> map = IterUtil.toMap(keys, keys);
|
||||
Assert.assertEquals(keys, new ArrayList<>(map.keySet()));
|
||||
Assert.assertEquals(keys, new ArrayList<>(map.values()));
|
||||
|
||||
map = IterUtil.toMap(keys.iterator(), keys.iterator());
|
||||
Assert.assertEquals(keys, new ArrayList<>(map.keySet()));
|
||||
Assert.assertEquals(keys, new ArrayList<>(map.values()));
|
||||
|
||||
map = IterUtil.toMap(keys.iterator(), keys.iterator(), true);
|
||||
Assert.assertEquals(keys, new ArrayList<>(map.keySet()));
|
||||
Assert.assertEquals(keys, new ArrayList<>(map.values()));
|
||||
|
||||
map = IterUtil.toMap(keys, keys, true);
|
||||
Assert.assertEquals(keys, new ArrayList<>(map.keySet()));
|
||||
Assert.assertEquals(keys, new ArrayList<>(map.values()));
|
||||
|
||||
map = IterUtil.toMap(keys, Function.identity());
|
||||
Assert.assertEquals(keys, new ArrayList<>(map.keySet()));
|
||||
Assert.assertEquals(keys, new ArrayList<>(map.values()));
|
||||
|
||||
map = IterUtil.toMap(keys, Function.identity(), Function.identity());
|
||||
Assert.assertEquals(keys, new ArrayList<>(map.keySet()));
|
||||
Assert.assertEquals(keys, new ArrayList<>(map.values()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToListMap() {
|
||||
List<Integer> keys = Arrays.asList(1, 2, 3, 4);
|
||||
|
||||
Map<Boolean, List<Integer>> map = IterUtil.toListMap(keys, i -> (i & 1) == 0, Function.identity());
|
||||
Assert.assertEquals(Arrays.asList(2, 4), map.get(true));
|
||||
Assert.assertEquals(Arrays.asList(1, 3), map.get(false));
|
||||
|
||||
map = IterUtil.toListMap(keys, i -> (i & 1) == 0);
|
||||
Assert.assertEquals(Arrays.asList(2, 4), map.get(true));
|
||||
Assert.assertEquals(Arrays.asList(1, 3), map.get(false));
|
||||
|
||||
map = new LinkedHashMap<>();
|
||||
Map<Boolean, List<Integer>> rawMap = IterUtil.toListMap(map, keys, i -> (i & 1) == 0, Function.identity());
|
||||
Assert.assertSame(rawMap, map);
|
||||
Assert.assertEquals(Arrays.asList(2, 4), rawMap.get(true));
|
||||
Assert.assertEquals(Arrays.asList(1, 3), rawMap.get(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsIterable() {
|
||||
Iterator<Integer> iter = Arrays.asList(1, 2, 3).iterator();
|
||||
Assert.assertEquals(iter, IterUtil.asIterable(iter).iterator());
|
||||
Assert.assertNull(IterUtil.asIterable(null).iterator());
|
||||
|
||||
Enumeration<Integer> enumeration = new IteratorEnumeration<>(iter);
|
||||
Iterator<Integer> iter2 = IterUtil.asIterator(enumeration);
|
||||
Assert.assertEquals((Integer)1, iter2.next());
|
||||
Assert.assertEquals((Integer)2, iter2.next());
|
||||
Assert.assertEquals((Integer)3, iter2.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGet() {
|
||||
Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4).iterator();
|
||||
Assert.assertEquals((Integer)3, IterUtil.get(iter, 2));
|
||||
Assert.assertThrows(IllegalArgumentException.class, () -> IterUtil.get(iter, -1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFirst() {
|
||||
Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4).iterator();
|
||||
Assert.assertEquals((Integer)1, IterUtil.getFirst(iter));
|
||||
Assert.assertNull(IterUtil.getFirst(null));
|
||||
Assert.assertNull(IterUtil.getFirst(Collections.emptyIterator()));
|
||||
|
||||
Assert.assertEquals((Integer)2, IterUtil.getFirst(iter, t -> (t & 1) == 0));
|
||||
Assert.assertNull(IterUtil.getFirst((Iterator<Integer>)null, t -> (t & 1) == 0));
|
||||
Assert.assertNull(IterUtil.getFirst(Collections.emptyIterator(), Objects::nonNull));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFirstNoneNull() {
|
||||
Iterator<Integer> iter = Arrays.asList(null, 2, null, 4).iterator();
|
||||
Assert.assertEquals((Integer)2, IterUtil.getFirstNoneNull(iter));
|
||||
Assert.assertNull(IterUtil.getFirstNoneNull(null));
|
||||
Assert.assertNull(IterUtil.getFirstNoneNull(Collections.emptyIterator()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetElementType() {
|
||||
List<Object> list = Arrays.asList(null, "str", null);
|
||||
Assert.assertEquals(String.class, IterUtil.getElementType(list));
|
||||
Assert.assertNull(IterUtil.getElementType((Iterable<?>)null));
|
||||
Assert.assertNull(IterUtil.getElementType(Collections.emptyList()));
|
||||
|
||||
Assert.assertEquals(String.class, IterUtil.getElementType(list.iterator()));
|
||||
Assert.assertNull(IterUtil.getElementType((Iterator<?>)null));
|
||||
Assert.assertNull(IterUtil.getElementType(Collections.emptyIterator()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEdit() {
|
||||
Assert.assertEquals(
|
||||
Collections.singletonList("str"),
|
||||
IterUtil.edit(Arrays.asList(null, "str", null).iterator(), t -> t)
|
||||
);
|
||||
Assert.assertEquals(
|
||||
Collections.singletonList("str"),
|
||||
IterUtil.edit(Arrays.asList(null, "str", null).iterator(), null)
|
||||
);
|
||||
Assert.assertEquals(Collections.emptyList(), IterUtil.edit(null, t -> t));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove() {
|
||||
List<Integer> list = new ArrayList<>(Arrays.asList(1, null, null, 3));
|
||||
IterUtil.remove(list.iterator(), Objects::isNull);
|
||||
Assert.assertEquals(Arrays.asList(1, 3), list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterToList() {
|
||||
List<Integer> list1 = new ArrayList<>(Arrays.asList(1, null, null, 3));
|
||||
List<Integer> list2 = IterUtil.filterToList(list1.iterator(), Objects::nonNull);
|
||||
Assert.assertSame(list1, list1);
|
||||
Assert.assertEquals(Arrays.asList(1, 3), list2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFiltered() {
|
||||
Assert.assertNotNull(IterUtil.filtered(Collections.emptyIterator(), t -> true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
Assert.assertSame(Collections.emptyIterator(), IterUtil.empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrans() {
|
||||
Assert.assertNotNull(IterUtil.trans(Collections.emptyIterator(), t -> true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSize() {
|
||||
Assert.assertEquals(0, IterUtil.size((Iterator<?>)null));
|
||||
Assert.assertEquals(0, IterUtil.size(Collections.emptyIterator()));
|
||||
Assert.assertEquals(3, IterUtil.size(Arrays.asList(1, 2, 3).iterator()));
|
||||
|
||||
Assert.assertEquals(0, IterUtil.size((Iterable<?>)null));
|
||||
Assert.assertEquals(0, IterUtil.size(Collections.emptyList()));
|
||||
Assert.assertEquals(3, IterUtil.size(Arrays.asList(1, 2, 3)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEqualList() {
|
||||
Assert.assertFalse(IterUtil.isEqualList(null, Collections.emptyList()));
|
||||
Assert.assertFalse(IterUtil.isEqualList(Arrays.asList(1, 2, 3), Collections.emptyList()));
|
||||
Assert.assertFalse(IterUtil.isEqualList(Arrays.asList(1, 2, 3), Arrays.asList(1, 2)));
|
||||
Assert.assertTrue(IterUtil.isEqualList(Arrays.asList(1, 2, 3), Arrays.asList(1, 2, 3)));
|
||||
Assert.assertTrue(IterUtil.isEqualList(null, null));
|
||||
Assert.assertTrue(IterUtil.isEqualList(Collections.emptyList(), Collections.emptyList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClear() {
|
||||
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
|
||||
IterUtil.clear(list.iterator());
|
||||
Assert.assertTrue(list.isEmpty());
|
||||
Assert.assertThrows(UnsupportedOperationException.class, () -> IterUtil.clear(Arrays.asList(1, 2).iterator()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStr() {
|
||||
List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
Assert.assertEquals("[1, 2, 3]", IterUtil.toStr(list.iterator()));
|
||||
Assert.assertEquals("[1, 2, 3]", IterUtil.toStr(list.iterator(), Objects::toString));
|
||||
Assert.assertEquals("{1:2:3}", IterUtil.toStr(list.iterator(), Objects::toString, ":", "{", "}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForEach() {
|
||||
List<Integer> list = new ArrayList<>();
|
||||
IterUtil.forEach(Arrays.asList(1, 2, 3, 4).iterator(), list::add);
|
||||
Assert.assertEquals(Arrays.asList(1, 2, 3, 4), list);
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private static class Bean {
|
||||
private final Integer id;
|
||||
private final String name;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* test for {@link IteratorEnumeration}
|
||||
*/
|
||||
public class IteratorEnumerationTest {
|
||||
|
||||
@Test
|
||||
public void testHasMoreElements() {
|
||||
List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
IteratorEnumeration<Integer> enumeration = new IteratorEnumeration<>(list.iterator());
|
||||
Assert.assertTrue(enumeration.hasMoreElements());
|
||||
Assert.assertFalse(new IteratorEnumeration<>(Collections.emptyIterator()).hasMoreElements());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextElement() {
|
||||
List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
IteratorEnumeration<Integer> enumeration = new IteratorEnumeration<>(list.iterator());
|
||||
Assert.assertEquals((Integer)1, enumeration.nextElement());
|
||||
Assert.assertEquals((Integer)2, enumeration.nextElement());
|
||||
Assert.assertEquals((Integer)3, enumeration.nextElement());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* test for {@link LineIter}
|
||||
*/
|
||||
public class LineIterTest {
|
||||
|
||||
@Test
|
||||
public void testHasNext() {
|
||||
LineIter iter = getItrFromClasspathFile();
|
||||
Assert.assertTrue(iter.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNext() {
|
||||
LineIter iter = getItrFromClasspathFile();
|
||||
Assert.assertEquals("is first line", iter.next());
|
||||
Assert.assertEquals("is second line", iter.next());
|
||||
Assert.assertEquals("is third line", iter.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove() {
|
||||
LineIter iter = getItrFromClasspathFile();
|
||||
iter.next();
|
||||
Assert.assertThrows(UnsupportedOperationException.class, iter::remove);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFinish() {
|
||||
LineIter iter = getItrFromClasspathFile();
|
||||
iter.finish();
|
||||
Assert.assertThrows(NoSuchElementException.class, iter::next);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClose() throws IOException {
|
||||
URL url = LineIterTest.class.getClassLoader().getResource("text.txt");
|
||||
Assert.assertNotNull(url);
|
||||
FileInputStream inputStream = new FileInputStream(url.getFile());
|
||||
LineIter iter = new LineIter(inputStream, StandardCharsets.UTF_8);
|
||||
iter.close();
|
||||
Assert.assertThrows(NoSuchElementException.class, iter::next);
|
||||
Assert.assertThrows(IOException.class, inputStream::read);
|
||||
}
|
||||
|
||||
private static LineIter getItrFromClasspathFile() {
|
||||
URL url = LineIterTest.class.getClassLoader().getResource("text.txt");
|
||||
Assert.assertNotNull(url);
|
||||
FileInputStream inputStream = null;
|
||||
try {
|
||||
inputStream = new FileInputStream(url.getFile());
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
return new LineIter(bufferedReader);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* test for {@link PartitionIter}
|
||||
*/
|
||||
public class PartitionIterTest {
|
||||
|
||||
@Test
|
||||
public void testHasNext() {
|
||||
Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4).iterator();
|
||||
PartitionIter<Integer> partitionIter = new PartitionIter<>(iter, 2);
|
||||
Assert.assertTrue(partitionIter.hasNext());
|
||||
Assert.assertFalse(new PartitionIter<>(Collections.emptyIterator(), 1).hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNext() {
|
||||
Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4).iterator();
|
||||
PartitionIter<Integer> partitionIter = new PartitionIter<>(iter, 2);
|
||||
Assert.assertEquals(Arrays.asList(1, 2), partitionIter.next());
|
||||
Assert.assertEquals(Arrays.asList(3, 4), partitionIter.next());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package cn.hutool.core.collection.iter;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @author huangchengxing
|
||||
*/
|
||||
public class TransIterTest {
|
||||
|
||||
@Test
|
||||
public void testHasNext() {
|
||||
TransIter<Integer, String> iter = new TransIter<>(Arrays.asList(1, 2, 3).iterator(), String::valueOf);
|
||||
Assert.assertTrue(iter.hasNext());
|
||||
Assert.assertFalse(new TransIter<>(Collections.emptyIterator(), Function.identity()).hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNext() {
|
||||
TransIter<Integer, String> iter = new TransIter<>(Arrays.asList(1, 2, 3).iterator(), String::valueOf);
|
||||
Assert.assertEquals("1", iter.next());
|
||||
Assert.assertEquals("2", iter.next());
|
||||
Assert.assertEquals("3", iter.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove() {
|
||||
List<Integer> list = ListUtil.of(1, 2, 3);
|
||||
TransIter<Integer, String> iter = new TransIter<>(list.iterator(), String::valueOf);
|
||||
iter.next();
|
||||
iter.remove();
|
||||
iter.next();
|
||||
iter.remove();
|
||||
iter.next();
|
||||
iter.remove();
|
||||
Assert.assertTrue(list.isEmpty());
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Objects;
|
||||
|
||||
public class TimeUtilTest {
|
||||
@ -234,7 +233,49 @@ public class TimeUtilTest {
|
||||
@Test
|
||||
public void ofTest2(){
|
||||
final Instant instant = Objects.requireNonNull(DateUtil.parse("2022-02-22")).toInstant();
|
||||
final LocalDateTime of = TimeUtil.of((TemporalAccessor) instant);
|
||||
final LocalDateTime of = TimeUtil.of(instant);
|
||||
Console.log(of);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Test
|
||||
public void isInTest() {
|
||||
// 时间范围 8点-9点
|
||||
final LocalDateTime begin = LocalDateTime.parse("2019-02-02T08:00:00");
|
||||
final LocalDateTime end = LocalDateTime.parse("2019-02-02T09:00:00");
|
||||
|
||||
// 不在时间范围内 用例
|
||||
Assert.assertFalse(TimeUtil.isIn(LocalDateTime.parse("2019-02-02T06:00:00"), begin, end));
|
||||
Assert.assertFalse(TimeUtil.isIn(LocalDateTime.parse("2019-02-02T13:00:00"), begin, end));
|
||||
Assert.assertFalse(TimeUtil.isIn(LocalDateTime.parse("2019-02-01T08:00:00"), begin, end));
|
||||
Assert.assertFalse(TimeUtil.isIn(LocalDateTime.parse("2019-02-03T09:00:00"), begin, end));
|
||||
|
||||
// 在时间范围内 用例
|
||||
Assert.assertTrue(TimeUtil.isIn(LocalDateTime.parse("2019-02-02T08:00:00"), begin, end));
|
||||
Assert.assertTrue(TimeUtil.isIn(LocalDateTime.parse("2019-02-02T08:00:01"), begin, end));
|
||||
Assert.assertTrue(TimeUtil.isIn(LocalDateTime.parse("2019-02-02T08:11:00"), begin, end));
|
||||
Assert.assertTrue(TimeUtil.isIn(LocalDateTime.parse("2019-02-02T08:22:00"), begin, end));
|
||||
Assert.assertTrue(TimeUtil.isIn(LocalDateTime.parse("2019-02-02T08:59:59"), begin, end));
|
||||
Assert.assertTrue(TimeUtil.isIn(LocalDateTime.parse("2019-02-02T09:00:00"), begin, end));
|
||||
|
||||
// 测试边界条件
|
||||
Assert.assertTrue(TimeUtil.isIn(begin, begin, end, true, false));
|
||||
Assert.assertFalse(TimeUtil.isIn(begin, begin, end, false, false));
|
||||
Assert.assertTrue(TimeUtil.isIn(end, begin, end, false, true));
|
||||
Assert.assertFalse(TimeUtil.isIn(end, begin, end, false, false));
|
||||
|
||||
// begin、end互换
|
||||
Assert.assertTrue(TimeUtil.isIn(begin, end, begin, true, true));
|
||||
|
||||
// 比较当前时间范围
|
||||
final LocalDateTime now = LocalDateTime.now();
|
||||
Assert.assertTrue(TimeUtil.isIn(now, now.minusHours(1L), now.plusHours(1L)));
|
||||
Assert.assertFalse(TimeUtil.isIn(now, now.minusHours(1L), now.minusHours(2L)));
|
||||
Assert.assertFalse(TimeUtil.isIn(now, now.plusHours(1L), now.plusHours(2L)));
|
||||
|
||||
// 异常入参
|
||||
Assert.assertThrows(IllegalArgumentException.class, () -> TimeUtil.isIn(null, begin, end, false, false));
|
||||
Assert.assertThrows(IllegalArgumentException.class, () -> TimeUtil.isIn(begin, null, end, false, false));
|
||||
Assert.assertThrows(IllegalArgumentException.class, () -> TimeUtil.isIn(begin, begin, null, false, false));
|
||||
}
|
||||
}
|
||||
|
@ -47,14 +47,14 @@ public class CollectorUtilTest {
|
||||
|
||||
@Test
|
||||
public void testToEasyStream() {
|
||||
Stream<Integer> stream =Stream.of(1, 2, 3, 4)
|
||||
final Stream<Integer> stream =Stream.of(1, 2, 3, 4)
|
||||
.collect(CollectorUtil.toEasyStream());
|
||||
Assert.assertEquals(EasyStream.class, stream.getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToEntryStream() {
|
||||
Map<String, Integer> map = Stream.of(1, 2, 3, 4, 5)
|
||||
final Map<String, Integer> map = Stream.of(1, 2, 3, 4, 5)
|
||||
// 转为EntryStream
|
||||
.collect(CollectorUtil.toEntryStream(Function.identity(), String::valueOf))
|
||||
// 过滤偶数
|
||||
|
@ -218,7 +218,7 @@ public class EasyStreamTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPeek(){
|
||||
public void testPeek() {
|
||||
EasyStream.of("one", "two", "three", "four")
|
||||
.filter(e -> e.length() == 4)
|
||||
.peek(e -> Assert.assertEquals("four", e))
|
||||
@ -228,12 +228,12 @@ public class EasyStreamTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPeekIdx(){
|
||||
public void testPeekIdx() {
|
||||
EasyStream.of("one", "two", "three", "four")
|
||||
.filter(e -> e.length() == 4)
|
||||
.peekIdx((e,i) -> Assert.assertEquals("four:0", e + ":" + i))
|
||||
.peekIdx((e, i) -> Assert.assertEquals("four:0", e + ":" + i))
|
||||
.map(String::toUpperCase)
|
||||
.peekIdx((e,i) -> Assert.assertEquals("FOUR:0", e + ":" + i))
|
||||
.peekIdx((e, i) -> Assert.assertEquals("FOUR:0", e + ":" + i))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@ -431,7 +431,7 @@ public class EasyStreamTest {
|
||||
@Test
|
||||
public void testToTree() {
|
||||
Consumer<Object> test = o -> {
|
||||
List<Student> studentTree = EasyStream
|
||||
final List<Student> studentTree = EasyStream
|
||||
.of(
|
||||
Student.builder().id(1L).name("dromara").build(),
|
||||
Student.builder().id(2L).name("baomidou").build(),
|
||||
@ -464,7 +464,7 @@ public class EasyStreamTest {
|
||||
), studentTree);
|
||||
};
|
||||
test = test.andThen(o -> {
|
||||
List<Student> studentTree = EasyStream
|
||||
final List<Student> studentTree = EasyStream
|
||||
.of(
|
||||
Student.builder().id(1L).name("dromara").matchParent(true).build(),
|
||||
Student.builder().id(2L).name("baomidou").matchParent(true).build(),
|
||||
@ -501,7 +501,7 @@ public class EasyStreamTest {
|
||||
|
||||
@Test
|
||||
public void testFlatTree() {
|
||||
List<Student> studentTree = asList(
|
||||
final List<Student> studentTree = asList(
|
||||
Student.builder().id(1L).name("dromara")
|
||||
.children(asList(Student.builder().id(3L).name("hutool").parentId(1L)
|
||||
.children(singletonList(Student.builder().id(6L).name("looly").parentId(3L).build()))
|
||||
@ -551,9 +551,9 @@ public class EasyStreamTest {
|
||||
@Test
|
||||
public void testTransform() {
|
||||
final boolean result = EasyStream.of(1, 2, 3)
|
||||
.transform(EasyStream::toList)
|
||||
.map(List::isEmpty)
|
||||
.orElse(false);
|
||||
.transform(EasyStream::toList)
|
||||
.map(List::isEmpty)
|
||||
.orElse(false);
|
||||
Assert.assertFalse(result);
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,23 @@
|
||||
package cn.hutool.core.util;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.exceptions.CloneRuntimeException;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* test for {@link ObjUtil}
|
||||
*/
|
||||
public class ObjUtilTest {
|
||||
|
||||
@Test
|
||||
@ -56,43 +62,49 @@ public class ObjUtilTest {
|
||||
|
||||
final Iterable<Integer> list = ListUtil.of(1, 2, 3);
|
||||
Assert.assertEquals(3, ObjUtil.length(list));
|
||||
Assert.assertEquals(3, ObjUtil.length(Arrays.asList(1, 2, 3).iterator()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void containsTest(){
|
||||
final int[] array = new int[]{1,2,3,4,5};
|
||||
|
||||
final boolean contains = ObjUtil.contains(array, 1);
|
||||
Assert.assertTrue(contains);
|
||||
Assert.assertTrue(ObjUtil.contains(new int[]{1,2,3,4,5}, 1));
|
||||
Assert.assertFalse(ObjUtil.contains(null, 1));
|
||||
Assert.assertTrue(ObjUtil.contains("123", "3"));
|
||||
Map<Integer, Integer> map = new HashMap<>();
|
||||
map.put(1, 1);
|
||||
map.put(2, 2);
|
||||
Assert.assertTrue(ObjUtil.contains(map, 1));
|
||||
Assert.assertTrue(ObjUtil.contains(Arrays.asList(1, 2, 3).iterator(), 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloneTest() {
|
||||
final Obj obj = new Obj();
|
||||
final Obj obj2 = ObjUtil.clone(obj);
|
||||
Assert.assertEquals("OK", obj2.doSomeThing());
|
||||
}
|
||||
|
||||
static class Obj implements Cloneable {
|
||||
public String doSomeThing() {
|
||||
return "OK";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Obj clone() {
|
||||
try {
|
||||
return (Obj) super.clone();
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
throw new CloneRuntimeException(e);
|
||||
}
|
||||
}
|
||||
public void isNullTest() {
|
||||
Assert.assertTrue(ObjUtil.isNull(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringTest() {
|
||||
final ArrayList<String> strings = ListUtil.of("1", "2");
|
||||
final String result = ObjUtil.toString(strings);
|
||||
Assert.assertEquals("[1, 2]", result);
|
||||
public void isNotNullTest() {
|
||||
Assert.assertFalse(ObjUtil.isNotNull(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isEmptyTest() {
|
||||
Assert.assertTrue(ObjUtil.isEmpty(null));
|
||||
Assert.assertTrue(ObjUtil.isEmpty(new int[0]));
|
||||
Assert.assertTrue(ObjUtil.isEmpty(""));
|
||||
Assert.assertTrue(ObjUtil.isEmpty(Collections.emptyList()));
|
||||
Assert.assertTrue(ObjUtil.isEmpty(Collections.emptyMap()));
|
||||
Assert.assertTrue(ObjUtil.isEmpty(Collections.emptyIterator()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotEmptyTest() {
|
||||
Assert.assertFalse(ObjUtil.isNotEmpty(null));
|
||||
Assert.assertFalse(ObjUtil.isNotEmpty(new int[0]));
|
||||
Assert.assertFalse(ObjUtil.isNotEmpty(""));
|
||||
Assert.assertFalse(ObjUtil.isNotEmpty(Collections.emptyList()));
|
||||
Assert.assertFalse(ObjUtil.isNotEmpty(Collections.emptyMap()));
|
||||
Assert.assertFalse(ObjUtil.isNotEmpty(Collections.emptyIterator()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -113,6 +125,48 @@ public class ObjUtilTest {
|
||||
Assert.assertSame(val2, ObjUtil.defaultIfNull(null, Function.identity(), val2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloneTest() {
|
||||
Assert.assertNull(ObjUtil.clone(null));
|
||||
|
||||
final CloneableBean cloneableBean1 = new CloneableBean(1);
|
||||
final CloneableBean cloneableBean2 = ObjUtil.clone(cloneableBean1);
|
||||
Assert.assertEquals(cloneableBean1, cloneableBean2);
|
||||
|
||||
final SerializableBean serializableBean1 = new SerializableBean(2);
|
||||
final SerializableBean serializableBean2 = ObjUtil.clone(serializableBean1);
|
||||
Assert.assertEquals(serializableBean1, serializableBean2);
|
||||
|
||||
final Bean bean1 = new Bean(3);
|
||||
Assert.assertNull(ObjUtil.clone(bean1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloneIfPossibleTest() {
|
||||
Assert.assertNull(ObjUtil.clone(null));
|
||||
|
||||
final CloneableBean cloneableBean1 = new CloneableBean(1);
|
||||
Assert.assertEquals(cloneableBean1, ObjUtil.cloneIfPossible(cloneableBean1));
|
||||
|
||||
final SerializableBean serializableBean1 = new SerializableBean(2);
|
||||
Assert.assertEquals(serializableBean1, ObjUtil.cloneIfPossible(serializableBean1));
|
||||
|
||||
final Bean bean1 = new Bean(3);
|
||||
Assert.assertSame(bean1, ObjUtil.cloneIfPossible(bean1));
|
||||
|
||||
final ExceptionCloneableBean exceptionBean1 = new ExceptionCloneableBean(3);
|
||||
Assert.assertSame(exceptionBean1, ObjUtil.cloneIfPossible(exceptionBean1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloneByStreamTest() {
|
||||
Assert.assertNull(ObjUtil.cloneByStream(null));
|
||||
Assert.assertNull(ObjUtil.cloneByStream(new CloneableBean(1)));
|
||||
final SerializableBean serializableBean1 = new SerializableBean(2);
|
||||
Assert.assertEquals(serializableBean1, ObjUtil.cloneByStream(serializableBean1));
|
||||
Assert.assertNull(ObjUtil.cloneByStream(new Bean(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isBasicTypeTest(){
|
||||
final int a = 1;
|
||||
@ -121,9 +175,72 @@ public class ObjUtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloneIfPossibleTest() {
|
||||
final String a = "a";
|
||||
final String a2 = ObjUtil.cloneIfPossible(a);
|
||||
Assert.assertNotSame(a, a2);
|
||||
public void isValidIfNumberTest() {
|
||||
Assert.assertTrue(ObjUtil.isValidIfNumber(null));
|
||||
Assert.assertFalse(ObjUtil.isValidIfNumber(Double.NEGATIVE_INFINITY));
|
||||
Assert.assertFalse(ObjUtil.isValidIfNumber(Double.NaN));
|
||||
Assert.assertTrue(ObjUtil.isValidIfNumber(Double.MIN_VALUE));
|
||||
Assert.assertFalse(ObjUtil.isValidIfNumber(Float.NEGATIVE_INFINITY));
|
||||
Assert.assertFalse(ObjUtil.isValidIfNumber(Float.NaN));
|
||||
Assert.assertTrue(ObjUtil.isValidIfNumber(Float.MIN_VALUE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTest() {
|
||||
Assert.assertEquals(0, ObjUtil.compare(1, 1));
|
||||
Assert.assertEquals(1, ObjUtil.compare(1, null));
|
||||
Assert.assertEquals(-1, ObjUtil.compare(null, 1));
|
||||
|
||||
Assert.assertEquals(-1, ObjUtil.compare(1, null, true));
|
||||
Assert.assertEquals(1, ObjUtil.compare(null, 1, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTypeArgumentTest() {
|
||||
final Bean bean = new Bean(1);
|
||||
Assert.assertEquals(Integer.class, ObjUtil.getTypeArgument(bean));
|
||||
Assert.assertEquals(String.class, ObjUtil.getTypeArgument(bean, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringTest() {
|
||||
Assert.assertEquals("null", ObjUtil.toString(null));
|
||||
Assert.assertEquals(Collections.emptyMap().toString(), ObjUtil.toString(Collections.emptyMap()));
|
||||
Assert.assertEquals("[1, 2]", Arrays.asList("1", "2").toString());
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
private static class ExceptionCloneableBean implements Cloneable {
|
||||
private final Integer id;
|
||||
@Override
|
||||
protected Object clone() throws CloneNotSupportedException {
|
||||
throw new RuntimeException("can not clone this object");
|
||||
}
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
private static class CloneableBean implements Cloneable {
|
||||
private final Integer id;
|
||||
@Override
|
||||
protected Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
private static class SerializableBean implements Serializable {
|
||||
private final Integer id;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
private static class Bean implements TypeArgument<Integer, String> {
|
||||
private final Integer id;
|
||||
}
|
||||
|
||||
private interface TypeArgument<A, B> {};
|
||||
|
||||
}
|
||||
|
@ -43,4 +43,11 @@ public class RuntimeUtilTest {
|
||||
final int pid = RuntimeUtil.getPid();
|
||||
Assert.assertTrue(pid > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProcessorCountTest(){
|
||||
int cpu = RuntimeUtil.getProcessorCount();
|
||||
Console.log("cpu个数:{}", cpu);
|
||||
Assert.assertTrue(cpu > 0);
|
||||
}
|
||||
}
|
||||
|
3
hutool-core/src/test/resources/text.txt
Normal file
3
hutool-core/src/test/resources/text.txt
Normal file
@ -0,0 +1,3 @@
|
||||
is first line
|
||||
is second line
|
||||
is third line
|
@ -2,8 +2,9 @@ package cn.hutool.extra.ftp;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import cn.hutool.core.util.CharUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
@ -73,7 +74,12 @@ public abstract class AbstractFtp implements Closeable {
|
||||
* @since 5.7.5
|
||||
*/
|
||||
public boolean isDir(final String dir) {
|
||||
return cd(dir);
|
||||
final String workDir = pwd();
|
||||
try {
|
||||
return cd(dir);
|
||||
} finally {
|
||||
cd(workDir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,14 +91,35 @@ public abstract class AbstractFtp implements Closeable {
|
||||
public abstract boolean mkdir(String dir);
|
||||
|
||||
/**
|
||||
* 文件或目录是否存在
|
||||
* 文件或目录是否存在<br>
|
||||
* <ul>
|
||||
* <li>提供路径为空则返回{@code false}</li>
|
||||
* <li>提供路径非目录但是以'/'或'\'结尾返回{@code false}</li>
|
||||
* <li>文件名是'.'或者'..'返回{@code false}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param path 目录
|
||||
* @return 是否存在
|
||||
*/
|
||||
public boolean exist(final String path) {
|
||||
if (StrUtil.isBlank(path)) {
|
||||
return false;
|
||||
}
|
||||
// 目录验证
|
||||
if (isDir(path)) {
|
||||
return true;
|
||||
}
|
||||
if (CharUtil.isFileSeparator(path.charAt(path.length() - 1))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final String fileName = FileUtil.getName(path);
|
||||
final String dir = StrUtil.removeSuffix(path, fileName);
|
||||
if (".".equals(fileName) || "..".equals(fileName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 文件验证
|
||||
final String dir = StrUtil.defaultIfEmpty(StrUtil.removeSuffix(path, fileName), ".");
|
||||
final List<String> names;
|
||||
try {
|
||||
names = ls(dir);
|
||||
@ -180,7 +207,7 @@ public abstract class AbstractFtp implements Closeable {
|
||||
|
||||
/**
|
||||
* 下载文件-避免未完成的文件<br>
|
||||
* 来自:https://gitee.com/dromara/hutool/pulls/407<br>
|
||||
* 来自:<a href="https://gitee.com/dromara/hutool/pulls/407">https://gitee.com/dromara/hutool/pulls/407</a><br>
|
||||
* 此方法原理是先在目标文件同级目录下创建临时文件,下载之,等下载完毕后重命名,避免因下载错误导致的文件不完整。
|
||||
*
|
||||
* @param path 文件路径
|
||||
|
@ -89,5 +89,66 @@ public class FtpTest {
|
||||
name,
|
||||
FileUtil.file("d:/test/download/" + name));
|
||||
}
|
||||
|
||||
IoUtil.close(ftp);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void isDirTest() throws Exception {
|
||||
try (final Ftp ftp = new Ftp("127.0.0.1", 21)) {
|
||||
Console.log(ftp.pwd());
|
||||
ftp.isDir("/test");
|
||||
Console.log(ftp.pwd());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void existSftpTest() throws Exception {
|
||||
try (final Sftp ftp = new Sftp("127.0.0.1", 22, "test", "test")) {
|
||||
Console.log(ftp.pwd());
|
||||
Console.log(ftp.exist(null));
|
||||
Console.log(ftp.exist(""));
|
||||
Console.log(ftp.exist("."));
|
||||
Console.log(ftp.exist(".."));
|
||||
Console.log(ftp.exist("/"));
|
||||
Console.log(ftp.exist("a"));
|
||||
Console.log(ftp.exist("/home/test"));
|
||||
Console.log(ftp.exist("/home/test/"));
|
||||
Console.log(ftp.exist("/home/test//////"));
|
||||
Console.log(ftp.exist("/home/test/file1"));
|
||||
Console.log(ftp.exist("/home/test/file1/"));
|
||||
Console.log(ftp.exist("///////////"));
|
||||
Console.log(ftp.exist("./"));
|
||||
Console.log(ftp.exist("./file1"));
|
||||
Console.log(ftp.pwd());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void existFtpTest() throws Exception {
|
||||
try (final Ftp ftp = new Ftp("127.0.0.1", 21)) {
|
||||
Console.log(ftp.pwd());
|
||||
Console.log(ftp.exist(null));
|
||||
Console.log(ftp.exist(""));
|
||||
Console.log(ftp.exist("."));
|
||||
Console.log(ftp.exist(".."));
|
||||
Console.log(ftp.exist("/"));
|
||||
Console.log(ftp.exist("a"));
|
||||
Console.log(ftp.exist("/test"));
|
||||
Console.log(ftp.exist("/test/"));
|
||||
Console.log(ftp.exist("/test//////"));
|
||||
Console.log(ftp.exist("/test/.."));
|
||||
Console.log(ftp.exist("/test/."));
|
||||
Console.log(ftp.exist("/file1"));
|
||||
Console.log(ftp.exist("/file1/"));
|
||||
Console.log(ftp.exist("///////////"));
|
||||
Console.log(ftp.exist("./"));
|
||||
Console.log(ftp.exist("./file1"));
|
||||
Console.log(ftp.exist("./2/3/4/.."));
|
||||
Console.log(ftp.pwd());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ public enum GlobalHeaders {
|
||||
for (final Entry<String, List<String>> entry : headers.entrySet()) {
|
||||
name = entry.getKey();
|
||||
for (final String value : entry.getValue()) {
|
||||
this.header(name, StrUtil.nullToEmpty(value), false);
|
||||
this.header(name, StrUtil.emptyIfNull(value), false);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
@ -174,7 +174,7 @@ public abstract class HttpBase<T> {
|
||||
}
|
||||
|
||||
for (final Entry<String, String> entry : headers.entrySet()) {
|
||||
this.header(entry.getKey(), StrUtil.nullToEmpty(entry.getValue()), isOverride);
|
||||
this.header(entry.getKey(), StrUtil.emptyIfNull(entry.getValue()), isOverride);
|
||||
}
|
||||
return (T) this;
|
||||
}
|
||||
@ -207,7 +207,7 @@ public abstract class HttpBase<T> {
|
||||
for (final Entry<String, List<String>> entry : headers.entrySet()) {
|
||||
name = entry.getKey();
|
||||
for (final String value : entry.getValue()) {
|
||||
this.header(name, StrUtil.nullToEmpty(value), isOverride);
|
||||
this.header(name, StrUtil.emptyIfNull(value), isOverride);
|
||||
}
|
||||
}
|
||||
return (T) this;
|
||||
@ -227,7 +227,7 @@ public abstract class HttpBase<T> {
|
||||
}
|
||||
|
||||
for (final Entry<String, String> entry : headers.entrySet()) {
|
||||
this.header(entry.getKey(), StrUtil.nullToEmpty(entry.getValue()), false);
|
||||
this.header(entry.getKey(), StrUtil.emptyIfNull(entry.getValue()), false);
|
||||
}
|
||||
return (T) this;
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ public class HttpConnection {
|
||||
for (final Entry<String, List<String>> entry : headerMap.entrySet()) {
|
||||
name = entry.getKey();
|
||||
for (final String value : entry.getValue()) {
|
||||
this.header(name, StrUtil.nullToEmpty(value), isOverride);
|
||||
this.header(name, StrUtil.emptyIfNull(value), isOverride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ import cn.hutool.core.text.StrUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.CharUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.json.convert.JSONConverterOld;
|
||||
import cn.hutool.json.serialize.JSONString;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -207,9 +206,8 @@ public final class InternalJSONUtil {
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @param predicate 属性过滤器,{@link Predicate#test(Object)}为{@code true}保留
|
||||
* @return JSONObject
|
||||
*/
|
||||
public static JSONObject propertyPut(final JSONObject jsonObject, final Object key, final Object value, final Predicate<MutableEntry<String, Object>> predicate) {
|
||||
public static void propertyPut(final JSONObject jsonObject, final Object key, final Object value, final Predicate<MutableEntry<String, Object>> predicate) {
|
||||
final String[] path = StrUtil.splitToArray(Convert.toStr(key), CharUtil.DOT);
|
||||
final int last = path.length - 1;
|
||||
JSONObject target = jsonObject;
|
||||
@ -223,7 +221,6 @@ public final class InternalJSONUtil {
|
||||
target = nextTarget;
|
||||
}
|
||||
target.set(path[last], value, predicate);
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -259,8 +256,7 @@ public final class InternalJSONUtil {
|
||||
.setIgnoreNullValue(config.isIgnoreNullValue())
|
||||
.setTransientSupport(config.isTransientSupport())
|
||||
// 使用JSON转换器
|
||||
.setConverter((type, value) ->
|
||||
JSONConverterOld.convertWithCheck(type, value, null, config.isIgnoreError()));
|
||||
.setConverter(config.getConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -296,11 +292,10 @@ public final class InternalJSONUtil {
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param writer Writer
|
||||
* @return Writer
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public static Writer quote(final String str, final Writer writer) throws IORuntimeException {
|
||||
return quote(str, writer, true);
|
||||
public static void quote(final String str, final Writer writer) throws IORuntimeException {
|
||||
quote(str, writer, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,7 +2,6 @@ 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;
|
||||
@ -107,7 +106,10 @@ public interface JSON extends Cloneable, Serializable {
|
||||
* @see BeanPath#get(Object)
|
||||
* @since 4.0.6
|
||||
*/
|
||||
<T> T getByPath(String expression, Class<T> resultType);
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T> T getByPath(final String expression, final Class<T> resultType){
|
||||
return (T) getConfig().getConverter().convert(resultType, getByPath(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化打印JSON,缩进为4个空格
|
||||
@ -159,17 +161,6 @@ public interface JSON extends Cloneable, Serializable {
|
||||
*/
|
||||
Writer write(Writer writer, int indentFactor, int indent, final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException;
|
||||
|
||||
/**
|
||||
* 转为实体类对象,转换异常将被抛出
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param clazz 实体类
|
||||
* @return 实体类对象
|
||||
*/
|
||||
default <T> T toBean(final Class<T> clazz) {
|
||||
return toBean((Type) clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为实体类对象
|
||||
*
|
||||
@ -178,7 +169,8 @@ public interface JSON extends Cloneable, Serializable {
|
||||
* @return 实体类对象
|
||||
* @since 4.3.2
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T> T toBean(final Type type) {
|
||||
return JSONConverterOld.jsonConvert(type, this, getConfig());
|
||||
return (T) getConfig().getConverter().convert(type, this);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import cn.hutool.core.lang.mutable.MutableEntry;
|
||||
import cn.hutool.core.lang.mutable.MutableObj;
|
||||
import cn.hutool.core.text.StrJoiner;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.json.convert.JSONConverterOld;
|
||||
import cn.hutool.json.mapper.ArrayMapper;
|
||||
import cn.hutool.json.serialize.JSONWriter;
|
||||
|
||||
@ -193,11 +192,6 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
|
||||
return (index < 0 || index >= this.size()) ? defaultValue : this.rawList.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getByPath(final String expression, final Class<T> resultType) {
|
||||
return JSONConverterOld.jsonConvert(resultType, getByPath(expression), getConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an object value. This increases the array's length by one. <br>
|
||||
* 加入元素,数组长度+1,等同于 {@link JSONArray#add(Object)}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import cn.hutool.core.comparator.CompareUtil;
|
||||
import cn.hutool.core.convert.Converter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Comparator;
|
||||
@ -38,7 +39,6 @@ public class JSONConfig implements Serializable {
|
||||
* 是否支持transient关键字修饰和@Transient注解,如果支持,被修饰的字段或方法对应的字段将被忽略。
|
||||
*/
|
||||
private boolean transientSupport = true;
|
||||
|
||||
/**
|
||||
* 是否去除末尾多余0,例如如果为true,5.0返回5
|
||||
*/
|
||||
@ -47,6 +47,10 @@ public class JSONConfig implements Serializable {
|
||||
* 是否检查重复key
|
||||
*/
|
||||
private boolean checkDuplicate;
|
||||
/**
|
||||
* 自定义的类型转换器,用于在序列化、反序列化操作中实现对象类型转换
|
||||
*/
|
||||
private Converter converter;
|
||||
|
||||
/**
|
||||
* 创建默认的配置项
|
||||
@ -237,4 +241,20 @@ public class JSONConfig implements Serializable {
|
||||
this.checkDuplicate = checkDuplicate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义的类型转换器,用于在序列化、反序列化操作中实现对象类型转换
|
||||
* @return 转换器
|
||||
*/
|
||||
public Converter getConverter() {
|
||||
return converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自定义的类型转换器,用于在序列化、反序列化操作中实现对象类型转换
|
||||
* @param converter 转换器
|
||||
*/
|
||||
public void setConverter(final Converter converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package cn.hutool.json;
|
||||
import cn.hutool.core.convert.ConvertException;
|
||||
import cn.hutool.core.lang.getter.OptNullBasicTypeFromObjectGetter;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.json.convert.JSONConverterOld;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
@ -163,12 +162,13 @@ public interface JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K> {
|
||||
* @throws ConvertException 转换异常
|
||||
* @since 3.0.8
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T> T get(final K key, final Class<T> type) throws ConvertException {
|
||||
final Object value = this.getObj(key);
|
||||
if (ObjUtil.isNull(value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return JSONConverterOld.jsonConvert(type, value, getConfig());
|
||||
return (T) getConfig().getConverter().convert(type, value);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import cn.hutool.core.lang.mutable.MutableEntry;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.map.MapWrapper;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.json.convert.JSONConverterOld;
|
||||
import cn.hutool.json.mapper.ObjectMapper;
|
||||
import cn.hutool.json.serialize.JSONWriter;
|
||||
|
||||
@ -183,11 +182,6 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
|
||||
return this.getOrDefault(key, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getByPath(final String expression, final Class<T> resultType) {
|
||||
return JSONConverterOld.jsonConvert(resultType, getByPath(expression), getConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT 键值对到JSONObject中,在忽略null模式下,如果值为{@code null},将此键移除
|
||||
*
|
||||
|
@ -1,7 +1,6 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.json.convert.JSONConverterOld;
|
||||
import cn.hutool.json.serialize.JSONDeserializer;
|
||||
import cn.hutool.json.serialize.JSONString;
|
||||
|
||||
@ -29,8 +28,8 @@ public class JSONSupport implements JSONString, JSONDeserializer<Object> {
|
||||
*/
|
||||
@Override
|
||||
public Object deserialize(final JSON json) {
|
||||
final JSONSupport support = JSONConverterOld.jsonToBean(getClass(), json, false);
|
||||
BeanUtil.copyProperties(support, this);
|
||||
// TODO 经过两次转换,效率差,待优化
|
||||
BeanUtil.copyProperties(json.toBean(getClass()), this);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
16
hutool-json/src/main/java/cn/hutool/json/convert/JSONCompositeConverter.java
Executable file
16
hutool-json/src/main/java/cn/hutool/json/convert/JSONCompositeConverter.java
Executable file
@ -0,0 +1,16 @@
|
||||
package cn.hutool.json.convert;
|
||||
|
||||
import cn.hutool.core.convert.CompositeConverter;
|
||||
import cn.hutool.core.convert.ConvertException;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class JSONCompositeConverter extends CompositeConverter {
|
||||
|
||||
public static final JSONCompositeConverter INSTANCE = new JSONCompositeConverter();
|
||||
|
||||
@Override
|
||||
public <T> T convert(final Type type, final Object value, final T defaultValue, final boolean isCustomFirst) throws ConvertException {
|
||||
return super.convert(type, value, defaultValue, isCustomFirst);
|
||||
}
|
||||
}
|
53
hutool-json/src/test/java/Issue2555Test.java
Executable file
53
hutool-json/src/test/java/Issue2555Test.java
Executable file
@ -0,0 +1,53 @@
|
||||
import cn.hutool.json.JSON;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.hutool.json.serialize.JSONDeserializer;
|
||||
import cn.hutool.json.serialize.JSONObjectSerializer;
|
||||
import lombok.Data;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Issue2555Test {
|
||||
@Test
|
||||
public void serAndDeserTest(){
|
||||
JSONUtil.putSerializer(MyType.class, new MySerializer());
|
||||
JSONUtil.putDeserializer(MyType.class, new MyDeserializer());
|
||||
|
||||
final SimpleObj simpleObj = new SimpleObj();
|
||||
final MyType child = new MyType();
|
||||
child.setAddress("addrValue1");
|
||||
simpleObj.setMyType(child);
|
||||
|
||||
final String json = JSONUtil.toJsonStr(simpleObj);
|
||||
Assert.assertEquals("{\"myType\":{\"addr\":\"addrValue1\"}}", json);
|
||||
|
||||
//MyDeserializer不会被调用
|
||||
final SimpleObj simpleObj2 = JSONUtil.toBean(json, SimpleObj.class);
|
||||
Assert.assertEquals("addrValue1", simpleObj2.getMyType().getAddress());
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class MyType {
|
||||
private String address;
|
||||
}
|
||||
@Data
|
||||
public static class SimpleObj {
|
||||
private MyType myType;
|
||||
}
|
||||
|
||||
public static class MySerializer implements JSONObjectSerializer<MyType> {
|
||||
@Override
|
||||
public void serialize(JSONObject json, MyType bean) {
|
||||
json.set("addr", bean.getAddress());
|
||||
}
|
||||
}
|
||||
|
||||
public static class MyDeserializer implements JSONDeserializer<MyType> {
|
||||
@Override
|
||||
public MyType deserialize(JSON json) {
|
||||
final MyType myType = new MyType();
|
||||
myType.setAddress(((JSONObject)json).getStr("addr"));
|
||||
return myType;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,12 +3,15 @@ package cn.hutool.json.jwt;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import cn.hutool.json.jwt.signers.AlgorithmUtil;
|
||||
import cn.hutool.json.jwt.signers.JWTSigner;
|
||||
import cn.hutool.json.jwt.signers.JWTSignerUtil;
|
||||
import lombok.Data;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -159,4 +162,14 @@ public class JWTTest {
|
||||
final Date date = JWT.of(token).getPayload().getClaimsJson().getDate(JWTPayload.ISSUED_AT);
|
||||
Assert.assertEquals("2022-02-02", DateUtil.format(date, DatePattern.NORM_DATE_PATTERN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void issue2581Test(){
|
||||
final Map<String, Object> map = new HashMap<>();
|
||||
map.put("test2", 22222222222222L);
|
||||
final JWTSigner jwtSigner = JWTSignerUtil.createSigner(AlgorithmUtil.getAlgorithm("HS256"), Base64.getDecoder().decode("abcdefghijklmn"));
|
||||
final String sign = JWT.of().addPayloads(map).sign(jwtSigner);
|
||||
final Object test2 = JWT.of(sign).getPayload().getClaim("test2");
|
||||
Assert.assertEquals(Long.class, test2.getClass());
|
||||
}
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ public class StyleSet implements Serializable {
|
||||
|
||||
// 默认数字格式
|
||||
cellStyleForNumber = StyleUtil.cloneCellStyle(workbook, this.cellStyle);
|
||||
// 2表示:0.00
|
||||
cellStyleForNumber.setDataFormat((short) 2);
|
||||
// 0表示:General
|
||||
cellStyleForNumber.setDataFormat((short) 0);
|
||||
|
||||
// 默认日期格式
|
||||
this.cellStyleForDate = StyleUtil.cloneCellStyle(workbook, this.cellStyle);
|
||||
|
@ -449,7 +449,7 @@ public class CellUtil {
|
||||
}
|
||||
final Comment comment = drawing.createCellComment(anchor);
|
||||
comment.setString(factory.createRichTextString(commentText));
|
||||
comment.setAuthor(StrUtil.nullToEmpty(commentAuthor));
|
||||
comment.setAuthor(StrUtil.emptyIfNull(commentAuthor));
|
||||
cell.setCellComment(comment);
|
||||
}
|
||||
|
||||
|
@ -820,6 +820,19 @@ public class ExcelWriteTest {
|
||||
writer.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
//@Ignore
|
||||
public void writeDoubleTest(){
|
||||
// https://gitee.com/dromara/hutool/issues/I5PI5C
|
||||
final String path = "d:/test/doubleTest.xlsx";
|
||||
FileUtil.del(path);
|
||||
|
||||
final ExcelWriter writer = ExcelUtil.getWriter(path);
|
||||
writer.disableDefaultStyle();
|
||||
writer.writeRow(ListUtil.view(0.427d));
|
||||
writer.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void issueI466ZZTest(){
|
||||
|
@ -4,11 +4,14 @@ import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.lang.Console;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@ -94,4 +97,28 @@ public class WordWriterTest {
|
||||
word07Writer.addTable(list);
|
||||
word07Writer.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void writeBeanAsTableTest(){
|
||||
final List<Vo> of = ListUtil.of(
|
||||
new Vo("测试1", new BigDecimal(12), new BigDecimal(2)),
|
||||
new Vo("测试2", new BigDecimal(13), new BigDecimal(2)),
|
||||
new Vo("测试3", new BigDecimal(15), new BigDecimal(3)),
|
||||
new Vo("测试4", new BigDecimal(112), new BigDecimal(5))
|
||||
);
|
||||
|
||||
WordUtil.getWriter()
|
||||
.addTable(of)
|
||||
.flush(FileUtil.file("d:/test/beanValueTest.docx"))
|
||||
.close();
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
private static class Vo{
|
||||
private String name;
|
||||
private BigDecimal amount;
|
||||
private BigDecimal onYear;
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public class GroupedMap extends LinkedHashMap<String, LinkedHashMap<String, Stri
|
||||
public String get(final String group, final String key) {
|
||||
readLock.lock();
|
||||
try {
|
||||
final LinkedHashMap<String, String> map = this.get(StrUtil.nullToEmpty(group));
|
||||
final LinkedHashMap<String, String> map = this.get(StrUtil.emptyIfNull(group));
|
||||
if (MapUtil.isNotEmpty(map)) {
|
||||
return map.get(key);
|
||||
}
|
||||
@ -88,7 +88,7 @@ public class GroupedMap extends LinkedHashMap<String, LinkedHashMap<String, Stri
|
||||
* @return 此key之前存在的值,如果没有返回null
|
||||
*/
|
||||
public String put(String group, final String key, final String value) {
|
||||
group = StrUtil.nullToEmpty(group).trim();
|
||||
group = StrUtil.emptyIfNull(group).trim();
|
||||
writeLock.lock();
|
||||
try {
|
||||
final LinkedHashMap<String, String> valueMap = this.computeIfAbsent(group, k -> new LinkedHashMap<>());
|
||||
@ -121,7 +121,7 @@ public class GroupedMap extends LinkedHashMap<String, LinkedHashMap<String, Stri
|
||||
* @return 被删除的值,如果值不存在,返回null
|
||||
*/
|
||||
public String remove(String group, final String key) {
|
||||
group = StrUtil.nullToEmpty(group).trim();
|
||||
group = StrUtil.emptyIfNull(group).trim();
|
||||
writeLock.lock();
|
||||
try {
|
||||
final LinkedHashMap<String, String> valueMap = this.get(group);
|
||||
@ -141,7 +141,7 @@ public class GroupedMap extends LinkedHashMap<String, LinkedHashMap<String, Stri
|
||||
* @return 是否为空
|
||||
*/
|
||||
public boolean isEmpty(String group) {
|
||||
group = StrUtil.nullToEmpty(group).trim();
|
||||
group = StrUtil.emptyIfNull(group).trim();
|
||||
readLock.lock();
|
||||
try {
|
||||
final LinkedHashMap<String, String> valueMap = this.get(group);
|
||||
@ -172,7 +172,7 @@ public class GroupedMap extends LinkedHashMap<String, LinkedHashMap<String, Stri
|
||||
* @return 是否包含key
|
||||
*/
|
||||
public boolean containsKey(String group, final String key) {
|
||||
group = StrUtil.nullToEmpty(group).trim();
|
||||
group = StrUtil.emptyIfNull(group).trim();
|
||||
readLock.lock();
|
||||
try {
|
||||
final LinkedHashMap<String, String> valueMap = this.get(group);
|
||||
@ -193,7 +193,7 @@ public class GroupedMap extends LinkedHashMap<String, LinkedHashMap<String, Stri
|
||||
* @return 是否包含值
|
||||
*/
|
||||
public boolean containsValue(String group, final String value) {
|
||||
group = StrUtil.nullToEmpty(group).trim();
|
||||
group = StrUtil.emptyIfNull(group).trim();
|
||||
readLock.lock();
|
||||
try {
|
||||
final LinkedHashMap<String, String> valueMap = this.get(group);
|
||||
@ -213,7 +213,7 @@ public class GroupedMap extends LinkedHashMap<String, LinkedHashMap<String, Stri
|
||||
* @return this
|
||||
*/
|
||||
public GroupedMap clear(String group) {
|
||||
group = StrUtil.nullToEmpty(group).trim();
|
||||
group = StrUtil.emptyIfNull(group).trim();
|
||||
writeLock.lock();
|
||||
try {
|
||||
final LinkedHashMap<String, String> valueMap = this.get(group);
|
||||
@ -243,7 +243,7 @@ public class GroupedMap extends LinkedHashMap<String, LinkedHashMap<String, Stri
|
||||
* @return 键Set
|
||||
*/
|
||||
public Set<String> keySet(String group) {
|
||||
group = StrUtil.nullToEmpty(group).trim();
|
||||
group = StrUtil.emptyIfNull(group).trim();
|
||||
readLock.lock();
|
||||
try {
|
||||
final LinkedHashMap<String, String> valueMap = this.get(group);
|
||||
@ -263,7 +263,7 @@ public class GroupedMap extends LinkedHashMap<String, LinkedHashMap<String, Stri
|
||||
* @return 值
|
||||
*/
|
||||
public Collection<String> values(String group) {
|
||||
group = StrUtil.nullToEmpty(group).trim();
|
||||
group = StrUtil.emptyIfNull(group).trim();
|
||||
readLock.lock();
|
||||
try {
|
||||
final LinkedHashMap<String, String> valueMap = this.get(group);
|
||||
@ -293,7 +293,7 @@ public class GroupedMap extends LinkedHashMap<String, LinkedHashMap<String, Stri
|
||||
* @return 键值对
|
||||
*/
|
||||
public Set<Entry<String, String>> entrySet(String group) {
|
||||
group = StrUtil.nullToEmpty(group).trim();
|
||||
group = StrUtil.emptyIfNull(group).trim();
|
||||
readLock.lock();
|
||||
try {
|
||||
final LinkedHashMap<String, String> valueMap = this.get(group);
|
||||
|
@ -572,7 +572,7 @@ public final class Props extends Properties implements BasicTypeGetter<String>,
|
||||
* @since 4.6.3
|
||||
*/
|
||||
public <T> T fillBean(final T bean, String prefix) {
|
||||
prefix = StrUtil.nullToEmpty(StrUtil.addSuffixIfNot(prefix, StrUtil.DOT));
|
||||
prefix = StrUtil.emptyIfNull(StrUtil.addSuffixIfNot(prefix, StrUtil.DOT));
|
||||
|
||||
String key;
|
||||
for (final java.util.Map.Entry<Object, Object> entry : this.entrySet()) {
|
||||
|
@ -137,7 +137,7 @@ public class Profile implements Serializable {
|
||||
*/
|
||||
private String fixNameForProfile(final String name) {
|
||||
Assert.notBlank(name, "Setting name must be not blank !");
|
||||
final String actralProfile = StrUtil.nullToEmpty(this.profile);
|
||||
final String actralProfile = StrUtil.emptyIfNull(this.profile);
|
||||
if (false == name.contains(StrUtil.DOT)) {
|
||||
return StrUtil.format("{}/{}.setting", actralProfile, name);
|
||||
}
|
||||
|
@ -450,12 +450,13 @@ public class ImgUtil {
|
||||
*
|
||||
* @param srcImageFile 源图像文件
|
||||
* @param destDir 切片目标文件夹
|
||||
* @param formatName 格式名称,即图片格式后缀
|
||||
* @param rows 目标切片行数。默认2,必须是范围 [1, 20] 之内
|
||||
* @param cols 目标切片列数。默认2,必须是范围 [1, 20] 之内
|
||||
*/
|
||||
public static void sliceByRowsAndCols(final File srcImageFile, final File destDir, final int rows, final int cols) {
|
||||
public static void sliceByRowsAndCols(final File srcImageFile, final File destDir, final String formatName, final int rows, final int cols) {
|
||||
try {
|
||||
sliceByRowsAndCols(ImageIO.read(srcImageFile), destDir, rows, cols);
|
||||
sliceByRowsAndCols(ImageIO.read(srcImageFile), destDir, formatName, rows, cols);
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
@ -464,12 +465,13 @@ public class ImgUtil {
|
||||
/**
|
||||
* 图像切割(指定切片的行数和列数),默认RGB模式
|
||||
*
|
||||
* @param srcImage 源图像,如果非{@link BufferedImage},则默认使用RGB模式
|
||||
* @param destDir 切片目标文件夹
|
||||
* @param rows 目标切片行数。默认2,必须是范围 [1, 20] 之内
|
||||
* @param cols 目标切片列数。默认2,必须是范围 [1, 20] 之内
|
||||
* @param srcImage 源图像,如果非{@link BufferedImage},则默认使用RGB模式
|
||||
* @param destDir 切片目标文件夹
|
||||
* @param formatName 格式名称,即图片格式后缀
|
||||
* @param rows 目标切片行数。默认2,必须是范围 [1, 20] 之内
|
||||
* @param cols 目标切片列数。默认2,必须是范围 [1, 20] 之内
|
||||
*/
|
||||
public static void sliceByRowsAndCols(final Image srcImage, final File destDir, int rows, int cols) {
|
||||
public static void sliceByRowsAndCols(final Image srcImage, final File destDir, final String formatName, int rows, int cols) {
|
||||
if (false == destDir.exists()) {
|
||||
FileUtil.mkdir(destDir);
|
||||
} else if (false == destDir.isDirectory()) {
|
||||
@ -497,7 +499,7 @@ public class ImgUtil {
|
||||
for (int j = 0; j < cols; j++) {
|
||||
tag = cut(bi, new Rectangle(j * destWidth, i * destHeight, destWidth, destHeight));
|
||||
// 输出为文件
|
||||
ImageIO.write(toRenderedImage(tag), IMAGE_TYPE_JPEG, new File(destDir, "_r" + i + "_c" + j + ".jpg"));
|
||||
ImageIO.write(toRenderedImage(tag), formatName, new File(destDir, "_r" + i + "_c" + j + ".jpg"));
|
||||
}
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
@ -1359,10 +1361,10 @@ public class ImgUtil {
|
||||
/**
|
||||
* 根据文字创建透明背景的PNG图片
|
||||
*
|
||||
* @param str 文字
|
||||
* @param font 字体{@link Font}
|
||||
* @param fontColor 字体颜色,默认黑色
|
||||
* @param out 图片输出地
|
||||
* @param str 文字
|
||||
* @param font 字体{@link Font}
|
||||
* @param fontColor 字体颜色,默认黑色
|
||||
* @param out 图片输出地
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public static void createTransparentImage(String str, Font font, Color fontColor, ImageOutputStream out) throws IORuntimeException {
|
||||
@ -2072,7 +2074,7 @@ public class ImgUtil {
|
||||
r = (pixel & 0xff0000) >> 16;
|
||||
g = (pixel & 0xff00) >> 8;
|
||||
b = (pixel & 0xff);
|
||||
if(matchFilters(r, g, b, rgbFilters)){
|
||||
if (matchFilters(r, g, b, rgbFilters)) {
|
||||
continue;
|
||||
}
|
||||
countMap.merge(r + "-" + g + "-" + b, 1L, Long::sum);
|
||||
@ -2100,13 +2102,14 @@ public class ImgUtil {
|
||||
|
||||
/**
|
||||
* 给定RGB是否匹配过滤器中任何一个RGB颜色
|
||||
* @param r R
|
||||
* @param g G
|
||||
* @param b B
|
||||
*
|
||||
* @param r R
|
||||
* @param g G
|
||||
* @param b B
|
||||
* @param rgbFilters 颜色过滤器
|
||||
* @return 是否匹配
|
||||
*/
|
||||
private static boolean matchFilters(final int r, final int g, final int b, final int[]... rgbFilters){
|
||||
private static boolean matchFilters(final int r, final int g, final int b, final int[]... rgbFilters) {
|
||||
if (rgbFilters != null && rgbFilters.length > 0) {
|
||||
for (final int[] rgbFilter : rgbFilters) {
|
||||
if (r == rgbFilter[0] && g == rgbFilter[1] && b == rgbFilter[2]) {
|
||||
|
@ -89,7 +89,7 @@ public class ImgUtilTest {
|
||||
@Test
|
||||
@Ignore
|
||||
public void sliceByRowsAndColsTest() {
|
||||
ImgUtil.sliceByRowsAndCols(FileUtil.file("d:/test/logo.jpg"), FileUtil.file("d:/test/dest"), 1, 5);
|
||||
ImgUtil.sliceByRowsAndCols(FileUtil.file("d:/test/logo.jpg"), FileUtil.file("d:/test/dest"), ImgUtil.IMAGE_TYPE_JPEG, 1, 5);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user