This commit is contained in:
Looly 2022-06-18 23:03:06 +08:00
parent b0ed5bea9a
commit e9cf532af0
40 changed files with 327 additions and 415 deletions

View File

@ -7,7 +7,6 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.collection.SetUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.func.Editor;
import cn.hutool.core.lang.mutable.MutableEntry;
import cn.hutool.core.map.CaseInsensitiveMap;
import cn.hutool.core.map.MapUtil;
@ -36,6 +35,7 @@ import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
/**
@ -529,7 +529,7 @@ public class BeanUtil {
*/
public static Map<String, Object> beanToMap(final Object bean, final String... properties) {
int mapSize = 16;
Editor<MutableEntry<String, Object>> editor = null;
UnaryOperator<MutableEntry<String, Object>> editor = null;
if (ArrayUtil.isNotEmpty(properties)) {
mapSize = properties.length;
final Set<String> propertiesSet = SetUtil.of(properties);
@ -583,7 +583,7 @@ public class BeanUtil {
/**
* 对象转Map<br>
* 通过实现{@link Editor} 可以自定义字段值如果这个Editor返回null则忽略这个字段以便实现
* 通过实现{@link UnaryOperator} 可以自定义字段值如果这个Editor返回null则忽略这个字段以便实现
*
* <pre>
* 1. 字段筛选可以去除不需要的字段
@ -599,7 +599,7 @@ public class BeanUtil {
* @since 4.0.5
*/
public static Map<String, Object> beanToMap(final Object bean, final Map<String, Object> targetMap,
final boolean ignoreNullValue, final Editor<MutableEntry<String, Object>> keyEditor) {
final boolean ignoreNullValue, final UnaryOperator<MutableEntry<String, Object>> keyEditor) {
if (null == bean) {
return null;
}
@ -762,7 +762,7 @@ public class BeanUtil {
* @return bean
* @since 5.6.4
*/
public static <T> T edit(final T bean, final Editor<Field> editor) {
public static <T> T edit(final T bean, final UnaryOperator<Field> editor) {
if (bean == null) {
return null;
}
@ -772,7 +772,7 @@ public class BeanUtil {
if (ModifierUtil.isStatic(field)) {
continue;
}
editor.edit(field);
editor.apply(field);
}
return bean;
}

View File

@ -2,7 +2,6 @@ package cn.hutool.core.bean.copier;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.convert.Converter;
import cn.hutool.core.lang.func.Editor;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.lang.func.LambdaUtil;
import cn.hutool.core.lang.mutable.MutableEntry;
@ -14,6 +13,7 @@ import java.lang.reflect.Type;
import java.util.Map;
import java.util.Set;
import java.util.function.BiPredicate;
import java.util.function.UnaryOperator;
/**
* 属性拷贝选项<br>
@ -53,7 +53,7 @@ public class CopyOptions implements Serializable {
/**
* 字段属性名和属性值编辑器用于自定义属性转换规则例如驼峰转下划线等自定义属性值转换规则例如null转""
*/
protected Editor<MutableEntry<String, Object>> fieldEditor;
protected UnaryOperator<MutableEntry<String, Object>> fieldEditor;
/**
* 是否支持transient关键字修饰和@Transient注解如果支持被修饰的字段或方法对应的字段将被忽略
@ -250,7 +250,7 @@ public class CopyOptions implements Serializable {
* @return CopyOptions
* @since 5.4.2
*/
public CopyOptions setFieldEditor(final Editor<MutableEntry<String, Object>> editor) {
public CopyOptions setFieldEditor(final UnaryOperator<MutableEntry<String, Object>> editor) {
this.fieldEditor = editor;
return this;
}
@ -266,7 +266,7 @@ public class CopyOptions implements Serializable {
protected MutableEntry<String, Object> editField(final String fieldName, final Object fieldValue) {
final MutableEntry<String, Object> entry = new MutableEntry<>(fieldName, fieldValue);
return (null != this.fieldEditor) ?
this.fieldEditor.edit(entry) : entry;
this.fieldEditor.apply(entry) : entry;
}
/**

View File

@ -2,7 +2,6 @@ package cn.hutool.core.collection.iter;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.reflect.FieldUtil;
import cn.hutool.core.reflect.MethodUtil;
@ -623,27 +622,27 @@ public class IterUtil {
/**
* 过滤{@link Iterator}并将过滤后满足条件的元素添加到List中
*
* @param <E> 元素类型
* @param iter {@link Iterator}
* @param filter 过滤器保留{@link Filter#accept(Object)}{@code true}的元素
* @param <E> 元素类型
* @param iter {@link Iterator}
* @param predicate 过滤器{@link Predicate#test(Object)}{@code true}保留
* @return ArrayList
* @since 5.7.22
*/
public static <E> List<E> filterToList(final Iterator<E> iter, final Predicate<E> filter) {
return ListUtil.of(filtered(iter, filter));
public static <E> List<E> filterToList(final Iterator<E> iter, final Predicate<E> predicate) {
return ListUtil.of(filtered(iter, predicate));
}
/**
* 获取一个新的 {@link FilterIter}用于过滤指定元素
*
* @param iterator 被包装的 {@link Iterator}
* @param filter 过滤断言{@link Filter#accept(Object)}{@code true}时保留元素{@code false}抛弃元素
* @param <E> 元素类型
* @param iterator 被包装的 {@link Iterator}
* @param predicate 过滤断言{@link Predicate#test(Object)}{@code true}保留元素
* @param <E> 元素类型
* @return {@link FilterIter}
* @since 5.8.0
*/
public static <E> FilterIter<E> filtered(final Iterator<? extends E> iterator, final Predicate<? super E> filter) {
return new FilterIter<>(iterator, filter);
public static <E> FilterIter<E> filtered(final Iterator<? extends E> iterator, final Predicate<? super E> predicate) {
return new FilterIter<>(iterator, predicate);
}
/**

View File

@ -3,7 +3,6 @@ package cn.hutool.core.compress;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.text.StrUtil;
import java.io.Closeable;
@ -13,6 +12,7 @@ import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
@ -134,14 +134,14 @@ public class ZipReader implements Closeable {
* 解压到指定目录中
*
* @param outFile 解压到的目录
* @param entryFilter 过滤器排除不需要的文件
* @param entryFilter 过滤器只保留{@link Predicate#test(Object)}结果为{@code true}的文件
* @return 解压的目录
* @throws IORuntimeException IO异常
* @since 5.7.12
*/
public File readTo(final File outFile, final Filter<ZipEntry> entryFilter) throws IORuntimeException {
public File readTo(final File outFile, final Predicate<ZipEntry> entryFilter) throws IORuntimeException {
read((zipEntry) -> {
if (null == entryFilter || entryFilter.accept(zipEntry)) {
if (null == entryFilter || entryFilter.test(zipEntry)) {
//gitee issue #I4ZDQI
String path = zipEntry.getName();
if (FileUtil.isWindows()) {

View File

@ -1,7 +1,6 @@
package cn.hutool.core.io.watch;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.util.ArrayUtil;
import java.io.Closeable;
@ -21,6 +20,7 @@ import java.nio.file.WatchService;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
/**
* 文件监听服务此服务可以同时监听多个路径
@ -129,10 +129,10 @@ public class WatchServer extends Thread implements Closeable, Serializable {
* 执行事件获取并处理
*
* @param action 监听回调函数实现此函数接口用于处理WatchEvent事件
* @param watchFilter 监听过滤接口通过实现此接口过滤掉不需要监听的情况null表示不过滤
* @param watchFilter 监听过滤接口通过实现此接口过滤掉不需要监听的情况{@link Predicate#test(Object)}{@code true}保留null表示不过滤
* @since 5.4.0
*/
public void watch(final WatchAction action, final Filter<WatchEvent<?>> watchFilter) {
public void watch(final WatchAction action, final Predicate<WatchEvent<?>> watchFilter) {
final WatchKey wk;
try {
wk = watchService.take();
@ -146,7 +146,7 @@ public class WatchServer extends Thread implements Closeable, Serializable {
for (final WatchEvent<?> event : wk.pollEvents()) {
// 如果监听文件检查当前事件是否与所监听文件关联
if (null != watchFilter && false == watchFilter.accept(event)) {
if (null != watchFilter && false == watchFilter.test(event)) {
continue;
}
@ -160,9 +160,9 @@ public class WatchServer extends Thread implements Closeable, Serializable {
* 执行事件获取并处理
*
* @param watcher {@link Watcher}
* @param watchFilter 监听过滤接口通过实现此接口过滤掉不需要监听的情况null表示不过滤
* @param watchFilter 监听过滤接口通过实现此接口过滤掉不需要监听的情况{@link Predicate#test(Object)}{@code true}保留null表示不过滤
*/
public void watch(final Watcher watcher, final Filter<WatchEvent<?>> watchFilter) {
public void watch(final Watcher watcher, final Predicate<WatchEvent<?>> watchFilter) {
watch((event, currentPath)->{
final WatchEvent.Kind<?> kind = event.kind();

View File

@ -1,24 +0,0 @@
package cn.hutool.core.lang.func;
/**
* 编辑器接口常用于对于集合中的元素做统一编辑<br>
* 此编辑器两个作用
*
* <pre>
* 1如果返回值为{@code null}表示此值被抛弃
* 2对对象做修改
* </pre>
*
* @param <T> 被编辑对象类型
* @author Looly
*/
@FunctionalInterface
public interface Editor<T> {
/**
* 修改过滤后的结果
*
* @param t 被过滤的对象
* @return 修改后的对象如果被过滤返回{@code null}
*/
T edit(T t);
}

View File

@ -1,17 +0,0 @@
package cn.hutool.core.lang.func;
/**
* 过滤器接口
*
* @author Looly
*/
@FunctionalInterface
public interface Filter<T> {
/**
* 是否接受对象
*
* @param t 检查的对象
* @return 是否接受对象
*/
boolean accept(T t);
}

View File

@ -24,31 +24,31 @@ public class LambdaInfo {
private final Class<?> clazz;
private final SerializedLambda lambda;
public LambdaInfo(Executable executable, SerializedLambda lambda) {
public LambdaInfo(final Executable executable, final SerializedLambda lambda) {
if (executable instanceof Method) {
Method method = (Method) executable;
final Method method = (Method) executable;
this.parameterTypes = method.getGenericParameterTypes();
this.returnType = method.getGenericReturnType();
this.name = method.getName();
} else if (executable instanceof Constructor) {
Constructor<?> constructor = (Constructor<?>) executable;
final Constructor<?> constructor = (Constructor<?>) executable;
this.parameterTypes = constructor.getGenericParameterTypes();
this.returnType = constructor.getDeclaringClass();
this.name = constructor.getName();
} else {
throw new IllegalArgumentException("Unsupported executable type: " + executable.getClass());
}
int index = lambda.getInstantiatedMethodType().indexOf(";)");
final int index = lambda.getInstantiatedMethodType().indexOf(";)");
if (index > -1) {
boolean isArray = lambda.getInstantiatedMethodType().startsWith("([");
final boolean isArray = lambda.getInstantiatedMethodType().startsWith("([");
if (isArray) {
try {
this.instantiatedTypes = new Type[]{Class.forName(lambda.getInstantiatedMethodType().replace("/", ".").substring(0, index).substring(1) + ";")};
} catch (ClassNotFoundException e) {
} catch (final ClassNotFoundException e) {
throw new IllegalStateException(e);
}
} else {
String[] instantiatedTypeNames = lambda.getInstantiatedMethodType().substring(2, index).split(";L");
final String[] instantiatedTypeNames = lambda.getInstantiatedMethodType().substring(2, index).split(";L");
this.instantiatedTypes = new Type[instantiatedTypeNames.length];
for (int i = 0; i < instantiatedTypeNames.length; i++) {
this.instantiatedTypes[i] = ClassLoaderUtil.loadClass(instantiatedTypeNames[i]);

View File

@ -1,18 +0,0 @@
package cn.hutool.core.lang.func;
/**
* 匹配接口
*
* @param <T> 匹配的对象类型
* @author Looly
*/
@FunctionalInterface
public interface Matcher<T> {
/**
* 给定对象是否匹配
*
* @param t 对象
* @return 是否匹配
*/
boolean match(T t);
}

View File

@ -1,22 +0,0 @@
package cn.hutool.core.lang.func;
/**
* 替换器<br>
* 通过实现此接口完成指定类型对象的替换操作替换后的目标类型依旧为指定类型
*
* @author looly
*
* @param <T> 被替换操作的类型
* @since 4.1.5
*/
@FunctionalInterface
public interface Replacer<T> {
/**
* 替换指定类型为目标类型
*
* @param t 被替换的对象
* @return 替代后的对象
*/
T replace(T t);
}

View File

@ -5,8 +5,6 @@ import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.collection.iter.ArrayIter;
import cn.hutool.core.collection.iter.IterUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.func.Editor;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.reflect.ConstructorUtil;
import cn.hutool.core.reflect.TypeReference;
import cn.hutool.core.text.StrUtil;
@ -32,6 +30,8 @@ import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
/**
@ -658,7 +658,7 @@ public class MapUtil {
* @return 编辑后的Map
*/
@SuppressWarnings("unchecked")
public static <K, V> Map<K, V> edit(final Map<K, V> map, final Editor<Entry<K, V>> editor) {
public static <K, V> Map<K, V> edit(final Map<K, V> map, final UnaryOperator<Entry<K, V>> editor) {
if (null == map || null == editor) {
return map;
}
@ -673,7 +673,7 @@ public class MapUtil {
Entry<K, V> modified;
for (final Entry<K, V> entry : map.entrySet()) {
modified = editor.edit(entry);
modified = editor.apply(entry);
if (null != modified) {
map2.put(modified.getKey(), modified.getValue());
}
@ -689,18 +689,18 @@ public class MapUtil {
* 1过滤出需要的对象如果返回null表示这个元素对象抛弃
* </pre>
*
* @param <K> Key类型
* @param <V> Value类型
* @param map Map
* @param filter 过滤器接口{@code null}返回原Map
* @param <K> Key类型
* @param <V> Value类型
* @param map Map
* @param predicate 过滤器接口{@link Predicate#test(Object)}{@code true}保留{@code null}返回原Map
* @return 过滤后的Map
* @since 3.1.0
*/
public static <K, V> Map<K, V> filter(final Map<K, V> map, final Filter<Entry<K, V>> filter) {
if (null == map || null == filter) {
public static <K, V> Map<K, V> filter(final Map<K, V> map, final Predicate<Entry<K, V>> predicate) {
if (null == map || null == predicate) {
return map;
}
return edit(map, t -> filter.accept(t) ? t : null);
return edit(map, t -> predicate.test(t) ? t : null);
}

View File

@ -5,10 +5,9 @@ import cn.hutool.core.collection.iter.EnumerationIter;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.JNDIUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.text.StrUtil;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
@ -40,6 +39,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Predicate;
/**
* 网络相关工具
@ -424,11 +424,11 @@ public class NetUtil {
/**
* 获取所有满足过滤条件的本地IP地址对象
*
* @param addressFilter 过滤器null表示不过滤获取所有地址
* @param addressPredicate 过滤器{@link Predicate#test(Object)}{@code true}保留null表示不过滤获取所有地址
* @return 过滤后的地址对象列表
* @since 4.5.17
*/
public static LinkedHashSet<InetAddress> localAddressList(final Filter<InetAddress> addressFilter) {
public static LinkedHashSet<InetAddress> localAddressList(final Predicate<InetAddress> addressPredicate) {
final Enumeration<NetworkInterface> networkInterfaces;
try {
networkInterfaces = NetworkInterface.getNetworkInterfaces();
@ -447,7 +447,7 @@ public class NetUtil {
final Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
while (inetAddresses.hasMoreElements()) {
final InetAddress inetAddress = inetAddresses.nextElement();
if (inetAddress != null && (null == addressFilter || addressFilter.accept(inetAddress))) {
if (inetAddress != null && (null == addressPredicate || addressPredicate.test(inetAddress))) {
ipSet.add(inetAddress);
}
}
@ -462,7 +462,7 @@ public class NetUtil {
* 此方法不会抛出异常获取失败将返回{@code null}<br>
* <p>
* 参考<a href="http://stackoverflow.com/questions/9481865/getting-the-ip-address-of-the-current-machine-using-java">
* http://stackoverflow.com/questions/9481865/getting-the-ip-address-of-the-current-machine-using-java</a>
* http://stackoverflow.com/questions/9481865/getting-the-ip-address-of-the-current-machine-using-java</a>
*
* @return 本机网卡IP地址获取失败返回{@code null}
* @since 3.0.7

View File

@ -4,7 +4,6 @@ import cn.hutool.core.annotation.Alias;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.map.WeakConcurrentMap;
import cn.hutool.core.text.StrUtil;
@ -13,6 +12,7 @@ import cn.hutool.core.util.ArrayUtil;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
/**
* 反射中{@link Field}字段工具类包括字段获取和字段赋值
@ -125,13 +125,13 @@ public class FieldUtil {
* 如果子类与父类中存在同名字段则这两个字段同时存在子类字段在前父类字段在后
*
* @param beanClass
* @param fieldFilter field过滤器过滤掉不需要的field
* @param fieldPredicate field过滤器过滤掉不需要的field{@link Predicate#test(Object)}{@code true}保留null表示全部保留
* @return 字段列表
* @throws SecurityException 安全检查异常
* @since 5.7.14
*/
public static Field[] getFields(final Class<?> beanClass, final Filter<Field> fieldFilter) throws SecurityException {
return ArrayUtil.filter(getFields(beanClass), fieldFilter);
public static Field[] getFields(final Class<?> beanClass, final Predicate<Field> fieldPredicate) throws SecurityException {
return ArrayUtil.filter(getFields(beanClass), fieldPredicate);
}
/**

View File

@ -9,7 +9,6 @@ import cn.hutool.core.exceptions.InvocationTargetRuntimeException;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Singleton;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.map.WeakConcurrentMap;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
@ -21,6 +20,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
/**
* 反射中{@link Method}相关工具类包括方法获取和方法执行<br>
@ -67,21 +67,21 @@ public class MethodUtil {
/**
* 获得指定类过滤后的Public方法列表<br>
*
* @param clazz 查找方法的类
* @param filter 过滤器
* @param clazz 查找方法的类
* @param predicate 过滤器{@link Predicate#test(Object)}{@code true}保留null表示保留全部
* @return 过滤后的方法数组
*/
public static Method[] getPublicMethods(final Class<?> clazz, final Filter<Method> filter) {
public static Method[] getPublicMethods(final Class<?> clazz, final Predicate<Method> predicate) {
if (null == clazz) {
return null;
}
final Method[] methods = getPublicMethods(clazz);
if (null == filter) {
if (null == predicate) {
return methods;
}
return ArrayUtil.filter(methods, filter);
return ArrayUtil.filter(methods, predicate);
}
/**
@ -298,16 +298,16 @@ public class MethodUtil {
/**
* 获得指定类过滤后的Public方法列表
*
* @param clazz 查找方法的类
* @param filter 过滤器
* @param clazz 查找方法的类
* @param predicate 过滤器{@link Predicate#test(Object)}{@code true}保留null表示全部保留
* @return 过滤后的方法列表
* @throws SecurityException 安全异常
*/
public static Method[] getMethods(final Class<?> clazz, final Filter<Method> filter) throws SecurityException {
public static Method[] getMethods(final Class<?> clazz, final Predicate<Method> predicate) throws SecurityException {
if (null == clazz) {
return null;
}
return ArrayUtil.filter(getMethods(clazz), filter);
return ArrayUtil.filter(getMethods(clazz), predicate);
}
/**
@ -566,7 +566,7 @@ public class MethodUtil {
* @param args 参数对象
* @return 结果
* @throws InvocationTargetException 目标方法执行异常
* @throws IllegalAccessException 访问权限异常
* @throws IllegalAccessException 访问权限异常
*/
@SuppressWarnings("unchecked")
public static <T> T invokeRaw(final Object obj, final Method method, final Object... args) throws InvocationTargetException, IllegalAccessException {

View File

@ -4,9 +4,9 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.comparator.VersionComparator;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.lang.func.Matcher;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.math.NumberUtil;
import cn.hutool.core.regex.ReUtil;
import cn.hutool.core.text.finder.CharFinder;
import cn.hutool.core.text.finder.Finder;
import cn.hutool.core.text.finder.StrFinder;
@ -14,8 +14,6 @@ import cn.hutool.core.text.split.SplitUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.math.NumberUtil;
import cn.hutool.core.regex.ReUtil;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
@ -3701,7 +3699,7 @@ public class CharSequenceUtil {
/**
* 替换所有正则匹配的文本并使用自定义函数决定如何替换<br>
* replaceFun可以通过{@link Matcher}提取出匹配到的内容的不同部分然后经过重新处理组装变成新的内容放回原位
* replaceFun可以提取出匹配到的内容的不同部分然后经过重新处理组装变成新的内容放回原位
*
* <pre class="code">
* replace(this.content, "(\\d+)", parameters -&gt; "-" + parameters.group(1) + "-")
@ -3994,12 +3992,12 @@ public class CharSequenceUtil {
* 过滤字符串
*
* @param str 字符串
* @param filter 过滤器{@link Filter#accept(Object)}返回{@code true}保留字符
* @param predicate 过滤器{@link Predicate#test(Object)}{@code true}保留字符
* @return 过滤后的字符串
* @since 5.4.0
*/
public static String filter(final CharSequence str, final Filter<Character> filter) {
if (str == null || filter == null) {
public static String filter(final CharSequence str, final Predicate<Character> predicate) {
if (str == null || predicate == null) {
return str(str);
}
@ -4008,7 +4006,7 @@ public class CharSequenceUtil {
char c;
for (int i = 0; i < len; i++) {
c = str.charAt(i);
if (filter.accept(c)) {
if (predicate.test(c)) {
sb.append(c);
}
}
@ -4361,12 +4359,12 @@ public class CharSequenceUtil {
* @return 是否全部匹配
* @since 3.2.3
*/
public static boolean isAllCharMatch(final CharSequence value, final Matcher<Character> matcher) {
public static boolean isAllCharMatch(final CharSequence value, final Predicate<Character> matcher) {
if (StrUtil.isBlank(value)) {
return false;
}
for (int i = value.length(); --i >= 0; ) {
if (false == matcher.match(value.charAt(i))) {
if (false == matcher.test(value.charAt(i))) {
return false;
}
}

View File

@ -5,7 +5,8 @@ import cn.hutool.core.text.replacer.ReplacerChain;
/**
* XML特殊字符转义<br>
* https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents<br>
* <a href="https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents">
* https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents</a><br>
*
* <pre>
* &amp; (ampersand) 替换为 &amp;amp;

View File

@ -1,11 +1,12 @@
package cn.hutool.core.text.finder;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Matcher;
import java.util.function.Predicate;
/**
* 字符匹配查找器<br>
* 查找满足指定{@link Matcher} 匹配的字符所在位置此类长用于查找某一类字符如数字等
* 查找满足指定{@link Predicate} 匹配的字符所在位置此类长用于查找某一类字符如数字等
*
* @since 5.7.14
* @author looly
@ -13,13 +14,13 @@ import cn.hutool.core.lang.func.Matcher;
public class CharMatcherFinder extends TextFinder {
private static final long serialVersionUID = 1L;
private final Matcher<Character> matcher;
private final Predicate<Character> matcher;
/**
* 构造
* @param matcher 被查找的字符匹配器
*/
public CharMatcherFinder(final Matcher<Character> matcher) {
public CharMatcherFinder(final Predicate<Character> matcher) {
this.matcher = matcher;
}
@ -29,13 +30,13 @@ public class CharMatcherFinder extends TextFinder {
final int limit = getValidEndIndex();
if(negative){
for (int i = from; i > limit; i--) {
if(matcher.match(text.charAt(i))){
if(null == matcher || matcher.test(text.charAt(i))){
return i;
}
}
} else {
for (int i = from; i < limit; i++) {
if(matcher.match(text.charAt(i))){
if(null == matcher || matcher.test(text.charAt(i))){
return i;
}
}

View File

@ -1,8 +1,7 @@
package cn.hutool.core.text.replacer;
import cn.hutool.core.lang.func.Replacer;
import java.io.Serializable;
import java.util.function.UnaryOperator;
/**
* 抽象字符串替换类<br>
@ -11,7 +10,7 @@ import java.io.Serializable;
* @author looly
* @since 4.1.5
*/
public abstract class StrReplacer implements Replacer<CharSequence>, Serializable {
public abstract class StrReplacer implements UnaryOperator<CharSequence>, Serializable {
private static final long serialVersionUID = 1L;
/**
@ -25,7 +24,7 @@ public abstract class StrReplacer implements Replacer<CharSequence>, Serializabl
protected abstract int replace(CharSequence str, int pos, StringBuilder out);
@Override
public CharSequence replace(final CharSequence t) {
public CharSequence apply(final CharSequence t) {
final int len = t.length();
final StringBuilder builder = new StringBuilder(len);
int pos = 0;//当前位置

View File

@ -2,11 +2,10 @@ package cn.hutool.core.tree;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Filter;
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.core.text.StrUtil;
import java.io.PrintWriter;
import java.io.StringWriter;
@ -14,6 +13,7 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* 通过转换器将你的实体转化为TreeNodeMap节点实体 属性都存在此处,属性有序可支持排序
@ -202,28 +202,28 @@ public class Tree<T> extends LinkedHashMap<String, Object> implements Node<T> {
/**
* 递归过滤并生成新的树<br>
* 通过{@link Filter}指定的过滤规则本节点或子节点满足过滤条件则保留当前节点否则抛弃节点及其子节点
* 通过{@link Predicate}指定的过滤规则本节点或子节点满足过滤条件则保留当前节点否则抛弃节点及其子节点
*
* @param filter 节点过滤规则函数只需处理本级节点本身即可
* @param predicate 节点过滤规则函数只需处理本级节点本身即可{@link Predicate#test(Object)}{@code true}保留null表示全部保留
* @return 过滤后的节点{@code null} 表示不满足过滤要求丢弃之
* @see #filter(Filter)
* @see #filter(Predicate)
* @since 5.7.17
*/
public Tree<T> filterNew(final Filter<Tree<T>> filter) {
return cloneTree().filter(filter);
public Tree<T> filterNew(final Predicate<Tree<T>> predicate) {
return cloneTree().filter(predicate);
}
/**
* 递归过滤当前树注意此方法会修改当前树<br>
* 通过{@link Filter}指定的过滤规则本节点或子节点满足过滤条件则保留当前节点及其所有子节点否则抛弃节点及其子节点
* 通过{@link Predicate}指定的过滤规则本节点或子节点满足过滤条件则保留当前节点及其所有子节点否则抛弃节点及其子节点
*
* @param filter 节点过滤规则函数只需处理本级节点本身即可
* @param predicate 节点过滤规则函数只需处理本级节点本身即可{@link Predicate#test(Object)}{@code true}保留null表示保留全部
* @return 过滤后的节点{@code null} 表示不满足过滤要求丢弃之
* @see #filterNew(Filter)
* @see #filterNew(Predicate)
* @since 5.7.17
*/
public Tree<T> filter(final Filter<Tree<T>> filter) {
if(filter.accept(this)){
public Tree<T> filter(final Predicate<Tree<T>> predicate) {
if (null == predicate || predicate.test(this)) {
// 本节点满足则包括所有子节点都保留
return this;
}
@ -234,12 +234,12 @@ public class Tree<T> extends LinkedHashMap<String, Object> implements Node<T> {
final List<Tree<T>> filteredChildren = new ArrayList<>(children.size());
Tree<T> filteredChild;
for (final Tree<T> child : children) {
filteredChild = child.filter(filter);
filteredChild = child.filter(predicate);
if (null != filteredChild) {
filteredChildren.add(filteredChild);
}
}
if(CollUtil.isNotEmpty(filteredChildren)){
if (CollUtil.isNotEmpty(filteredChildren)) {
// 子节点有符合过滤条件的节点则本节点保留
return this.setChildren(filteredChildren);
} else {
@ -258,7 +258,7 @@ public class Tree<T> extends LinkedHashMap<String, Object> implements Node<T> {
* @return this
*/
public Tree<T> setChildren(final List<Tree<T>> children) {
if(null == children){
if (null == children) {
this.remove(treeNodeConfig.getChildrenKey());
}
this.put(treeNodeConfig.getChildrenKey(), children);

View File

@ -6,9 +6,6 @@ import cn.hutool.core.collection.UniqueKeySet;
import cn.hutool.core.comparator.CompareUtil;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Editor;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.lang.func.Matcher;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrJoiner;
import cn.hutool.core.text.StrUtil;
@ -27,6 +24,8 @@ import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
/**
@ -164,7 +163,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* @since 3.0.7
*/
@SuppressWarnings("unchecked")
public static <T> T firstMatch(final Matcher<T> matcher, final T... array) {
public static <T> T firstMatch(final Predicate<T> matcher, final T... array) {
final int index = matchIndex(matcher, array);
if (index < 0) {
return null;
@ -183,7 +182,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* @since 5.6.6
*/
@SuppressWarnings("unchecked")
public static <T> int matchIndex(final Matcher<T> matcher, final T... array) {
public static <T> int matchIndex(final Predicate<T> matcher, final T... array) {
return matchIndex(matcher, 0, array);
}
@ -198,11 +197,10 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* @since 5.7.3
*/
@SuppressWarnings("unchecked")
public static <T> int matchIndex(final Matcher<T> matcher, final int beginIndexInclude, final T... array) {
Assert.notNull(matcher, "Matcher must be not null !");
public static <T> int matchIndex(final Predicate<T> matcher, final int beginIndexInclude, final T... array) {
if (isNotEmpty(array)) {
for (int i = beginIndexInclude; i < array.length; i++) {
if (matcher.match(array[i])) {
if (null == matcher || matcher.test(array[i])) {
return i;
}
}
@ -654,7 +652,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* @return 编辑后的数组
* @since 5.3.3
*/
public static <T> T[] edit(final T[] array, final Editor<T> editor) {
public static <T> T[] edit(final T[] array, final UnaryOperator<T> editor) {
if (null == editor) {
return array;
}
@ -662,7 +660,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
final ArrayList<T> list = new ArrayList<>(array.length);
T modified;
for (final T t : array) {
modified = editor.edit(t);
modified = editor.apply(t);
if (null != modified) {
list.add(modified);
}
@ -676,20 +674,20 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* 过滤过程通过传入的Filter实现来过滤返回需要的元素内容这个Filter实现可以实现以下功能
*
* <pre>
* 1过滤出需要的对象{@link Filter#accept(Object)}方法返回true的对象将被加入结果集合中
* 1过滤出需要的对象{@link Predicate#test(Object)}{@code true}对象将被加入结果集合中
* </pre>
*
* @param <T> 数组元素类型
* @param array 数组
* @param filter 过滤器接口用于定义过滤规则{@code null}返回原集合
* @param <T> 数组元素类型
* @param array 数组
* @param predicate 过滤器接口用于定义过滤规则{@link Predicate#test(Object)}{@code true}保留{@code null}返回原集合
* @return 过滤后的数组
* @since 3.2.1
*/
public static <T> T[] filter(final T[] array, final Filter<T> filter) {
if (null == array || null == filter) {
public static <T> T[] filter(final T[] array, final Predicate<T> predicate) {
if (null == array || null == predicate) {
return array;
}
return edit(array, t -> filter.accept(t) ? t : null);
return edit(array, t -> predicate.test(t) ? t : null);
}
/**
@ -1240,8 +1238,8 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* @return 连接后的字符串
* @since 5.3.3
*/
public static <T> String join(final T[] array, final CharSequence conjunction, final Editor<T> editor) {
return StrJoiner.of(conjunction).append(array, (t) -> String.valueOf(editor.edit(t))).toString();
public static <T> String join(final T[] array, final CharSequence conjunction, final UnaryOperator<T> editor) {
return StrJoiner.of(conjunction).append(array, (t) -> String.valueOf(editor.apply(t))).toString();
}
/**

View File

@ -12,7 +12,7 @@ public class AlwaysTrueMatcher implements PartMatcher {
public static AlwaysTrueMatcher INSTANCE = new AlwaysTrueMatcher();
@Override
public boolean match(final Integer t) {
public boolean test(final Integer t) {
return true;
}

View File

@ -37,7 +37,7 @@ public class BoolArrayMatcher implements PartMatcher {
}
@Override
public boolean match(final Integer value) {
public boolean test(final Integer value) {
if (null == value || value >= bValues.length) {
return false;
}

View File

@ -30,9 +30,9 @@ public class DayOfMonthMatcher extends BoolArrayMatcher {
* @return 是否匹配
*/
public boolean match(final int value, final int month, final boolean isLeapYear) {
return (super.match(value) // 在约定日范围内的某一天
return (super.test(value) // 在约定日范围内的某一天
//匹配器中用户定义了最后一天31表示最后一天
|| (value > 27 && match(31) && isLastDayOfMonth(value, month, isLeapYear)));
|| (value > 27 && test(31) && isLastDayOfMonth(value, month, isLeapYear)));
}
/**

View File

@ -1,6 +1,6 @@
package cn.hutool.cron.pattern.matcher;
import cn.hutool.core.lang.func.Matcher;
import java.util.function.Predicate;
/**
* 表达式中的某个位置部分匹配器<br>
@ -8,7 +8,7 @@ import cn.hutool.core.lang.func.Matcher;
*
* @author Looly
*/
public interface PartMatcher extends Matcher<Integer> {
public interface PartMatcher extends Predicate<Integer> {
/**
* 获取指定值之后的匹配值也可以是指定值本身

View File

@ -80,7 +80,7 @@ public class PatternMatcher {
* @since 5.8.0
*/
public boolean matchWeek(final int dayOfWeekValue) {
return matchers[5].match(dayOfWeekValue);
return matchers[5].test(dayOfWeekValue);
}
/**
@ -96,13 +96,13 @@ public class PatternMatcher {
* @return 如果匹配返回 {@code true}, 否则返回 {@code false}
*/
private boolean match(final int second, final int minute, final int hour, final int dayOfMonth, final int month, final int dayOfWeek, final int year) {
return ((second < 0) || matchers[0].match(second)) // 匹配秒非秒匹配模式下始终返回true
&& matchers[1].match(minute)// 匹配分
&& matchers[2].match(hour)// 匹配时
return ((second < 0) || matchers[0].test(second)) // 匹配秒非秒匹配模式下始终返回true
&& matchers[1].test(minute)// 匹配分
&& matchers[2].test(hour)// 匹配时
&& matchDayOfMonth(matchers[3], dayOfMonth, month, Year.isLeap(year))// 匹配日
&& matchers[4].match(month) // 匹配月
&& matchers[5].match(dayOfWeek)// 匹配周
&& matchers[6].match(year);// 匹配年
&& matchers[4].test(month) // 匹配月
&& matchers[5].test(dayOfWeek)// 匹配周
&& matchers[6].test(year);// 匹配年
}
/**
@ -117,7 +117,7 @@ public class PatternMatcher {
private static boolean matchDayOfMonth(final PartMatcher matcher, final int dayOfMonth, final int month, final boolean isLeapYear) {
return ((matcher instanceof DayOfMonthMatcher) //
? ((DayOfMonthMatcher) matcher).match(dayOfMonth, month, isLeapYear) //
: matcher.match(dayOfMonth));
: matcher.test(dayOfMonth));
}
//endregion

View File

@ -18,7 +18,7 @@ public class YearValueMatcher implements PartMatcher {
}
@Override
public boolean match(final Integer t) {
public boolean test(final Integer t) {
return valueList.contains(t);
}

View File

@ -1,10 +1,10 @@
package cn.hutool.extra.compress.archiver;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.text.StrUtil;
import java.io.Closeable;
import java.io.File;
import java.util.function.Predicate;
/**
* 数据归档封装归档即将几个文件或目录打成一个压缩包
@ -27,11 +27,11 @@ public interface Archiver extends Closeable {
* 将文件或目录加入归档目录采取递归读取方式按照层级加入
*
* @param file 文件或目录
* @param filter 文件过滤器指定哪些文件或目录可以加入{@link Filter#accept(Object)}为true时加入
* @param predicate 文件过滤器指定哪些文件或目录可以加入{@link Predicate#test(Object)}{@code true}时加入null表示全部加入
* @return this
*/
default Archiver add(final File file, final Filter<File> filter) {
return add(file, StrUtil.SLASH, filter);
default Archiver add(final File file, final Predicate<File> predicate) {
return add(file, StrUtil.SLASH, predicate);
}
/**
@ -39,10 +39,10 @@ public interface Archiver extends Closeable {
*
* @param file 文件或目录
* @param path 文件或目录的初始路径null表示位于根路径
* @param filter 文件过滤器指定哪些文件或目录可以加入{@link Filter#accept(Object)}为true时加入
* @param filter 文件过滤器指定哪些文件或目录可以加入{@link Predicate#test(Object)}{@code true}保留null表示全部加入
* @return this
*/
Archiver add(File file, String path, Filter<File> filter);
Archiver add(File file, String path, Predicate<File> filter);
/**
* 结束已经增加的文件归档此方法不会关闭归档流可以继续添加文件

View File

@ -3,9 +3,8 @@ package cn.hutool.extra.compress.archiver;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
@ -13,6 +12,7 @@ import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.channels.SeekableByteChannel;
import java.util.function.Predicate;
/**
* 7zip格式的归档封装
@ -77,7 +77,7 @@ public class SevenZArchiver implements Archiver {
}
@Override
public SevenZArchiver add(final File file, final String path, final Filter<File> filter) {
public SevenZArchiver add(final File file, final String path, final Predicate<File> filter) {
try {
addInternal(file, path, filter);
} catch (final IOException e) {
@ -118,19 +118,19 @@ public class SevenZArchiver implements Archiver {
*
* @param file 文件或目录
* @param path 文件或目录的初始路径null表示位于根路径
* @param filter 文件过滤器指定哪些文件或目录可以加入{@link Filter#accept(Object)}为true时加入
* @param filter 文件过滤器指定哪些文件或目录可以加入{@link Predicate#test(Object)}{@code true}保留null表示保留全部
*/
private void addInternal(final File file, final String path, final Filter<File> filter) throws IOException {
if (null != filter && false == filter.accept(file)) {
private void addInternal(final File file, final String path, final Predicate<File> filter) throws IOException {
if (null != filter && false == filter.test(file)) {
return;
}
final SevenZOutputFile out = this.sevenZOutputFile;
final String entryName;
if(StrUtil.isNotEmpty(path)){
if (StrUtil.isNotEmpty(path)) {
// 非空拼接路径格式为path/name
entryName = StrUtil.addSuffixIfNot(path, StrUtil.SLASH) + file.getName();
} else{
} else {
// 路径空直接使用文件名或目录名
entryName = file.getName();
}
@ -139,7 +139,7 @@ public class SevenZArchiver implements Archiver {
if (file.isDirectory()) {
// 目录遍历写入
final File[] files = file.listFiles();
if(ArrayUtil.isNotEmpty(files)){
if (ArrayUtil.isNotEmpty(files)) {
for (final File childFile : files) {
addInternal(childFile, entryName, filter);
}

View File

@ -3,9 +3,8 @@ package cn.hutool.extra.compress.archiver;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.extra.compress.CompressException;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
@ -17,6 +16,7 @@ import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.function.Predicate;
/**
* 数据归档封装归档即将几个文件或目录打成一个压缩包<br>
@ -86,26 +86,26 @@ public class StreamArchiver implements Archiver {
}
//特殊设置
if(this.out instanceof TarArchiveOutputStream){
((TarArchiveOutputStream)out).setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
} else if(this.out instanceof ArArchiveOutputStream){
((ArArchiveOutputStream)out).setLongFileMode(ArArchiveOutputStream.LONGFILE_BSD);
if (this.out instanceof TarArchiveOutputStream) {
((TarArchiveOutputStream) out).setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
} else if (this.out instanceof ArArchiveOutputStream) {
((ArArchiveOutputStream) out).setLongFileMode(ArArchiveOutputStream.LONGFILE_BSD);
}
}
/**
* 将文件或目录加入归档包目录采取递归读取方式按照层级加入
*
* @param file 文件或目录
* @param path 文件或目录的初始路径null表示位于根路径
* @param filter 文件过滤器指定哪些文件或目录可以加入{@link Filter#accept(Object)}为true时加入
* @param file 文件或目录
* @param path 文件或目录的初始路径null表示位于根路径
* @param predicate 文件过滤器指定哪些文件或目录可以加入{@link Predicate#test(Object)}{@code true}加入null表示全部加入
* @return this
* @throws IORuntimeException IO异常
*/
@Override
public StreamArchiver add(final File file, final String path, final Filter<File> filter) throws IORuntimeException {
public StreamArchiver add(final File file, final String path, final Predicate<File> predicate) throws IORuntimeException {
try {
addInternal(file, path, filter);
addInternal(file, path, predicate);
} catch (final IOException e) {
throw new IORuntimeException(e);
}
@ -140,21 +140,21 @@ public class StreamArchiver implements Archiver {
/**
* 将文件或目录加入归档包目录采取递归读取方式按照层级加入
*
* @param file 文件或目录
* @param path 文件或目录的初始路径{@code null}表示位于根路径
* @param filter 文件过滤器指定哪些文件或目录可以加入{@link Filter#accept(Object)}为true时加入
* @param file 文件或目录
* @param path 文件或目录的初始路径{@code null}表示位于根路径
* @param predicate 文件过滤器指定哪些文件或目录可以加入{@link Predicate#test(Object)}{@code true}加入
*/
private void addInternal(final File file, final String path, final Filter<File> filter) throws IOException {
if (null != filter && false == filter.accept(file)) {
private void addInternal(final File file, final String path, final Predicate<File> predicate) throws IOException {
if (null != predicate && false == predicate.test(file)) {
return;
}
final ArchiveOutputStream out = this.out;
final String entryName;
if(StrUtil.isNotEmpty(path)){
if (StrUtil.isNotEmpty(path)) {
// 非空拼接路径格式为path/name
entryName = StrUtil.addSuffixIfNot(path, StrUtil.SLASH) + file.getName();
} else{
} else {
// 路径空直接使用文件名或目录名
entryName = file.getName();
}
@ -163,9 +163,9 @@ public class StreamArchiver implements Archiver {
if (file.isDirectory()) {
// 目录遍历写入
final File[] files = file.listFiles();
if(ArrayUtil.isNotEmpty(files)){
if (ArrayUtil.isNotEmpty(files)) {
for (final File childFile : files) {
addInternal(childFile, entryName, filter);
addInternal(childFile, entryName, predicate);
}
}
} else {

View File

@ -1,10 +1,10 @@
package cn.hutool.extra.compress.extractor;
import cn.hutool.core.lang.func.Filter;
import org.apache.commons.compress.archivers.ArchiveEntry;
import java.io.Closeable;
import java.io.File;
import java.util.function.Predicate;
/**
* 归档数据解包封装用于将ziptar等包解包为文件
@ -19,7 +19,7 @@ public interface Extractor extends Closeable {
*
* @param targetDir 目标目录
*/
default void extract(final File targetDir){
default void extract(final File targetDir) {
extract(targetDir, null);
}
@ -27,9 +27,9 @@ public interface Extractor extends Closeable {
* 释放解压到指定目录结束后自动关闭流此方法只能调用一次
*
* @param targetDir 目标目录
* @param filter 解压文件过滤器用于指定需要释放的文件{@code null}表示不过滤{@link Filter#accept(Object)}true时释放
* @param predicate 解压文件过滤器用于指定需要释放的文件{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}时释放
*/
void extract(File targetDir, Filter<ArchiveEntry> filter);
void extract(File targetDir, Predicate<ArchiveEntry> predicate);
/**
* 无异常关闭

View File

@ -4,7 +4,6 @@ import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.text.StrUtil;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
@ -16,6 +15,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.SeekableByteChannel;
import java.util.RandomAccess;
import java.util.function.Predicate;
/**
* 7z格式数据解压器即将归档打包的数据释放
@ -30,7 +30,7 @@ public class SevenZExtractor implements Extractor, RandomAccess {
/**
* 构造
*
* @param file 包文件
* @param file 包文件
*/
public SevenZExtractor(final File file) {
this(file, null);
@ -53,7 +53,7 @@ public class SevenZExtractor implements Extractor, RandomAccess {
/**
* 构造
*
* @param in 包流
* @param in 包流
*/
public SevenZExtractor(final InputStream in) {
this(in, null);
@ -72,7 +72,7 @@ public class SevenZExtractor implements Extractor, RandomAccess {
/**
* 构造
*
* @param channel {@link SeekableByteChannel}
* @param channel {@link SeekableByteChannel}
*/
public SevenZExtractor(final SeekableByteChannel channel) {
this(channel, null);
@ -92,16 +92,10 @@ public class SevenZExtractor implements Extractor, RandomAccess {
}
}
/**
* 释放解压到指定目录结束后自动关闭流此方法只能调用一次
*
* @param targetDir 目标目录
* @param filter 解压文件过滤器用于指定需要释放的文件null表示不过滤{@link Filter#accept(Object)}为true时释放
*/
@Override
public void extract(final File targetDir, final Filter<ArchiveEntry> filter) {
public void extract(final File targetDir, final Predicate<ArchiveEntry> predicate) {
try {
extractInternal(targetDir, filter);
extractInternal(targetDir, predicate);
} catch (final IOException e) {
throw new IORuntimeException(e);
} finally {
@ -112,17 +106,17 @@ public class SevenZExtractor implements Extractor, RandomAccess {
/**
* 获取满足指定过滤要求的压缩包内的第一个文件流
*
* @param filter 用于指定需要释放的文件null表示不过滤{@link Filter#accept(Object)}为true时返回对应流
* @return 满足过滤要求的第一个文件的流,无满足条件的文件返回{@code null}
* @param predicate 用于指定需要释放的文件null表示不过滤{@link Predicate#test(Object)}{@code true}返回对应流
* @return 满足过滤要求的第一个文件的流, 无满足条件的文件返回{@code null}
* @since 5.7.14
*/
public InputStream getFirst(final Filter<ArchiveEntry> filter) {
public InputStream getFirst(final Predicate<ArchiveEntry> predicate) {
final SevenZFile sevenZFile = this.sevenZFile;
for(final SevenZArchiveEntry entry : sevenZFile.getEntries()){
if(null != filter && false == filter.accept(entry)){
for (final SevenZArchiveEntry entry : sevenZFile.getEntries()) {
if (null != predicate && false == predicate.test(entry)) {
continue;
}
if(entry.isDirectory()){
if (entry.isDirectory()) {
continue;
}
@ -143,24 +137,24 @@ public class SevenZExtractor implements Extractor, RandomAccess {
* @return 文件流无文件返回{@code null}
* @since 5.7.14
*/
public InputStream get(final String entryName){
return getFirst((entry)-> StrUtil.equals(entryName, entry.getName()));
public InputStream get(final String entryName) {
return getFirst((entry) -> StrUtil.equals(entryName, entry.getName()));
}
/**
* 释放解压到指定目录
*
* @param targetDir 目标目录
* @param filter 解压文件过滤器用于指定需要释放的文件null表示不过滤{@link Filter#accept(Object)}true时释放
* @param predicate 解压文件过滤器用于指定需要释放的文件null表示不过滤{@link Predicate#test(Object)}{@code true}时释放
* @throws IOException IO异常
*/
private void extractInternal(final File targetDir, final Filter<ArchiveEntry> filter) throws IOException {
private void extractInternal(final File targetDir, final Predicate<ArchiveEntry> predicate) throws IOException {
Assert.isTrue(null != targetDir && ((false == targetDir.exists()) || targetDir.isDirectory()), "target must be dir.");
final SevenZFile sevenZFile = this.sevenZFile;
SevenZArchiveEntry entry;
File outItemFile;
while (null != (entry = this.sevenZFile.getNextEntry())) {
if(null != filter && false == filter.accept(entry)){
if (null != predicate && false == predicate.test(entry)) {
continue;
}
outItemFile = FileUtil.file(targetDir, entry.getName());
@ -168,7 +162,7 @@ public class SevenZExtractor implements Extractor, RandomAccess {
// 创建对应目录
//noinspection ResultOfMethodCallIgnored
outItemFile.mkdirs();
} else if(entry.hasStream()){
} else if (entry.hasStream()) {
// 读取entry对应数据流
FileUtil.writeFromStream(new Seven7EntryInputStream(sevenZFile, entry), outItemFile);
} else {

View File

@ -4,7 +4,6 @@ import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.text.StrUtil;
import cn.hutool.extra.compress.CompressException;
import org.apache.commons.compress.archivers.ArchiveEntry;
@ -16,6 +15,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.function.Predicate;
/**
* 数据解压器即将归档打包的数据释放
@ -23,15 +23,15 @@ import java.nio.charset.Charset;
* @author looly
* @since 5.5.0
*/
public class StreamExtractor implements Extractor{
public class StreamExtractor implements Extractor {
private final ArchiveInputStream in;
/**
* 构造
*
* @param charset 编码
* @param file 包文件
* @param charset 编码
* @param file 包文件
*/
public StreamExtractor(final Charset charset, final File file) {
this(charset, null, file);
@ -85,12 +85,12 @@ public class StreamExtractor implements Extractor{
* 释放解压到指定目录结束后自动关闭流此方法只能调用一次
*
* @param targetDir 目标目录
* @param filter 解压文件过滤器用于指定需要释放的文件null表示不过滤{@link Filter#accept(Object)}true时释放
* @param predicate 解压文件过滤器用于指定需要释放的文件null表示不过滤{@link Predicate#test(Object)}{@code true}时释放
*/
@Override
public void extract(final File targetDir, final Filter<ArchiveEntry> filter) {
public void extract(final File targetDir, final Predicate<ArchiveEntry> predicate) {
try {
extractInternal(targetDir, filter);
extractInternal(targetDir, predicate);
} catch (final IOException e) {
throw new IORuntimeException(e);
} finally {
@ -102,16 +102,16 @@ public class StreamExtractor implements Extractor{
* 释放解压到指定目录
*
* @param targetDir 目标目录
* @param filter 解压文件过滤器用于指定需要释放的文件null表示不过滤{@link Filter#accept(Object)}为true时释放
* @param predicate 解压文件过滤器用于指定需要释放的文件null表示不过滤{@link Predicate#test(Object)}{@code true}释放
* @throws IOException IO异常
*/
private void extractInternal(final File targetDir, final Filter<ArchiveEntry> filter) throws IOException {
private void extractInternal(final File targetDir, final Predicate<ArchiveEntry> predicate) throws IOException {
Assert.isTrue(null != targetDir && ((false == targetDir.exists()) || targetDir.isDirectory()), "target must be dir.");
final ArchiveInputStream in = this.in;
ArchiveEntry entry;
File outItemFile;
while (null != (entry = in.getNextEntry())) {
if(null != filter && false == filter.accept(entry)){
if (null != predicate && false == predicate.test(entry)) {
continue;
}
if (false == in.canReadEntryData(entry)) {

View File

@ -4,10 +4,9 @@ import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.text.StrUtil;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
@ -21,6 +20,7 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
/**
* FTP客户端封装<br>
@ -340,11 +340,11 @@ public class Ftp extends AbstractFtp {
* 此方法自动过滤"."".."两种目录
*
* @param path 目录
* @param filter 过滤器null表示不过滤默认去掉"."".."两种目录
* @param predicate 过滤器null表示不过滤默认去掉"."".."两种目录
* @return 文件或目录列表
* @since 5.3.5
*/
public List<FTPFile> lsFiles(final String path, final Filter<FTPFile> filter) {
public List<FTPFile> lsFiles(final String path, final Predicate<FTPFile> predicate) {
final FTPFile[] ftpFiles = lsFiles(path);
if (ArrayUtil.isEmpty(ftpFiles)) {
return ListUtil.empty();
@ -355,7 +355,7 @@ public class Ftp extends AbstractFtp {
for (final FTPFile ftpFile : ftpFiles) {
fileName = ftpFile.getName();
if (false == StrUtil.equals(".", fileName) && false == StrUtil.equals("..", fileName)) {
if (null == filter || filter.accept(ftpFile)) {
if (null == predicate || predicate.test(ftpFile)) {
result.add(ftpFile);
}
}

View File

@ -3,7 +3,6 @@ package cn.hutool.extra.ssh;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.text.StrUtil;
import cn.hutool.extra.ftp.AbstractFtp;
import cn.hutool.extra.ftp.FtpConfig;
@ -23,6 +22,7 @@ import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.function.Predicate;
/**
* SFTP是Secure File Transfer Protocol的缩写安全文件传送协议可以为传输文件提供一种安全的加密方法<br>
@ -302,13 +302,13 @@ public class Sftp extends AbstractFtp {
* 遍历某个目录下所有文件或目录不会递归遍历<br>
* 此方法自动过滤"."".."两种目录
*
* @param path 遍历某个目录下所有文件或目录
* @param filter 文件或目录过滤器可以实现过滤器返回自己需要的文件或目录名列表
* @param path 遍历某个目录下所有文件或目录
* @param predicate 文件或目录过滤器可以实现过滤器返回自己需要的文件或目录名列表{@link Predicate#test(Object)}{@code true}保留
* @return 目录或文件名列表
* @since 4.0.5
*/
public List<String> ls(final String path, final Filter<LsEntry> filter) {
final List<LsEntry> entries = lsEntries(path, filter);
public List<String> ls(final String path, final Predicate<LsEntry> predicate) {
final List<LsEntry> entries = lsEntries(path, predicate);
if (CollUtil.isEmpty(entries)) {
return ListUtil.empty();
}
@ -331,18 +331,18 @@ public class Sftp extends AbstractFtp {
* 遍历某个目录下所有文件或目录生成LsEntry列表不会递归遍历<br>
* 此方法自动过滤"."".."两种目录
*
* @param path 遍历某个目录下所有文件或目录
* @param filter 文件或目录过滤器可以实现过滤器返回自己需要的文件或目录名列表
* @param path 遍历某个目录下所有文件或目录
* @param predicate 文件或目录过滤器可以实现过滤器返回自己需要的文件或目录名列表{@link Predicate#test(Object)}{@code true}保留
* @return 目录或文件名列表
* @since 5.3.5
*/
public List<LsEntry> lsEntries(final String path, final Filter<LsEntry> filter) {
public List<LsEntry> lsEntries(final String path, final Predicate<LsEntry> predicate) {
final List<LsEntry> entryList = new ArrayList<>();
try {
channel.ls(path, entry -> {
final String fileName = entry.getFilename();
if (false == StrUtil.equals(".", fileName) && false == StrUtil.equals("..", fileName)) {
if (null == filter || filter.accept(entry)) {
if (null == predicate || predicate.test(entry)) {
entryList.add(entry);
}
}

View File

@ -2,15 +2,14 @@ package cn.hutool.json;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.lang.mutable.MutableEntry;
import cn.hutool.core.map.CaseInsensitiveLinkedMap;
import cn.hutool.core.map.CaseInsensitiveTreeMap;
import cn.hutool.core.math.NumberUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.math.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.text.StrUtil;
import java.math.BigDecimal;
import java.util.Collection;
@ -18,6 +17,7 @@ import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Predicate;
/**
* 内部JSON工具类仅用于JSON内部使用
@ -138,9 +138,10 @@ public final class InternalJSONUtil {
* @param jsonObject JSONObject
* @param key
* @param value
* @param predicate 属性过滤器{@link Predicate#test(Object)}{@code true}保留
* @return JSONObject
*/
static JSONObject propertyPut(final JSONObject jsonObject, final Object key, final Object value, final Filter<MutableEntry<String, Object>> filter) {
static JSONObject 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;
@ -149,11 +150,11 @@ public final class InternalJSONUtil {
JSONObject nextTarget = target.getJSONObject(segment);
if (nextTarget == null) {
nextTarget = new JSONObject(target.getConfig());
target.setOnce(segment, nextTarget, filter);
target.setOnce(segment, nextTarget, predicate);
}
target = nextTarget;
}
target.setOnce(path[last], value, filter);
target.setOnce(path[last], value, predicate);
return jsonObject;
}

View File

@ -3,7 +3,6 @@ package cn.hutool.json;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.convert.impl.ArrayConverter;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.lang.mutable.Mutable;
import cn.hutool.core.lang.mutable.MutableEntry;
import cn.hutool.core.lang.mutable.MutableObj;
@ -20,6 +19,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;
import java.util.function.Predicate;
/**
* JSON数组<br>
@ -142,13 +142,13 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
*
* @param object 数组或集合或JSON数组字符串
* @param jsonConfig JSON选项
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
* @throws JSONException 非数组或集合
* @since 5.8.0
*/
public JSONArray(final Object object, final JSONConfig jsonConfig, final Filter<Mutable<Object>> filter) throws JSONException {
public JSONArray(final Object object, final JSONConfig jsonConfig, final Predicate<Mutable<Object>> predicate) throws JSONException {
this(DEFAULT_CAPACITY, jsonConfig);
ObjectMapper.of(object).map(this, filter);
ObjectMapper.of(object).map(this, predicate);
}
// endregion
@ -365,7 +365,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
}
final ArrayList<Object> list = new ArrayList<>(c.size());
for (final Object object : c) {
if(null == object && config.isIgnoreNullValue()){
if (null == object && config.isIgnoreNullValue()) {
continue;
}
this.add(index);
@ -407,15 +407,15 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
*
* @param index 位置
* @param element 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @param filter 过滤器可以修改值keyindex无法修改
* @param filter 过滤器可以修改值keyindex无法修改{@link Predicate#test(Object)}{@code true}保留null表示全部保留
* @return 替换的值即之前的值
* @since 5.8.0
*/
public Object set(final int index, Object element, final Filter<MutableEntry<Integer, Object>> filter) {
public Object set(final int index, Object element, final Predicate<MutableEntry<Integer, Object>> filter) {
// 添加前置过滤通过MutablePair实现过滤修改键值对等
if (null != filter) {
final MutableEntry<Integer, Object> pair = new MutableEntry<>(index, element);
if (filter.accept(pair)) {
if (filter.test(pair)) {
// 使用修改后的值
element = pair.getValue();
}
@ -426,7 +426,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
add(index, element);
return null;
}
if(null == element && config.isIgnoreNullValue()){
if (null == element && config.isIgnoreNullValue()) {
return null;
}
return this.rawList.set(index, JSONUtil.wrap(element, this.config));
@ -434,7 +434,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
@Override
public void add(int index, final Object element) {
if(null == element && config.isIgnoreNullValue()){
if (null == element && config.isIgnoreNullValue()) {
return;
}
if (index < this.size()) {
@ -444,7 +444,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
InternalJSONUtil.testValidity(element);
this.rawList.add(index, JSONUtil.wrap(element, this.config));
} else {
if(false == config.isIgnoreNullValue()){
if (false == config.isIgnoreNullValue()) {
while (index != this.size()) {
// 非末尾则填充null
this.add(null);
@ -517,14 +517,14 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
* 支持过滤器即选择哪些字段或值不写出
*
* @param indentFactor 每层缩进空格数
* @param filter 过滤器可以修改值keyindex无法修改
* @param predicate 过滤器可以修改值keyindex无法修改{@link Predicate#test(Object)}{@code true}保留
* @return JSON字符串
* @since 5.7.15
*/
public String toJSONString(final int indentFactor, final Filter<MutableEntry<Integer, Object>> filter) {
public String toJSONString(final int indentFactor, final Predicate<MutableEntry<Integer, Object>> predicate) {
final StringWriter sw = new StringWriter();
synchronized (sw.getBuffer()) {
return this.write(sw, indentFactor, 0, filter).toString();
return this.write(sw, indentFactor, 0, predicate).toString();
}
}
@ -540,18 +540,18 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
* @param writer writer
* @param indentFactor 缩进因子定义每一级别增加的缩进量
* @param indent 本级别缩进量
* @param filter 过滤器可以修改值keyindex无法修改
* @param predicate 过滤器可以修改值keyindex无法修改{@link Predicate#test(Object)}{@code true}保留
* @return Writer
* @throws JSONException JSON相关异常
* @since 5.7.15
*/
public Writer write(final Writer writer, final int indentFactor, final int indent, final Filter<MutableEntry<Integer, Object>> filter) throws JSONException {
public Writer write(final Writer writer, final int indentFactor, final int indent, final Predicate<MutableEntry<Integer, Object>> predicate) throws JSONException {
final JSONWriter jsonWriter = JSONWriter.of(writer, indentFactor, indent, config)
.beginArray();
CollUtil.forEach(this, (value, index) -> {
final MutableEntry<Integer, Object> pair = new MutableEntry<>(index, value);
if (null == filter || filter.accept(pair)) {
if (null == predicate || predicate.test(pair)) {
jsonWriter.writeValue(pair.getValue());
}
});
@ -570,24 +570,24 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
/**
* 原始添加添加的对象不做任何处理
*
* @param obj 添加的对象
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤
* @param obj 添加的对象
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
* @return 是否加入成功
* @since 5.8.0
*/
protected boolean addRaw(Object obj, final Filter<Mutable<Object>> filter) {
protected boolean addRaw(Object obj, final Predicate<Mutable<Object>> predicate) {
// 添加前置过滤通过MutablePair实现过滤修改键值对等
if (null != filter) {
if (null != predicate) {
final Mutable<Object> mutable = new MutableObj<>(obj);
if (filter.accept(mutable)) {
if (predicate.test(mutable)) {
// 使用修改后的值
obj = mutable.get();
}else{
} else {
// 键值对被过滤
return false;
}
}
if(null == obj && config.isIgnoreNullValue()){
if (null == obj && config.isIgnoreNullValue()) {
// 忽略空则不添加
return false;
}

View File

@ -1,7 +1,6 @@
package cn.hutool.json;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.lang.mutable.MutableEntry;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.map.MapWrapper;
@ -15,6 +14,7 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Map;
import java.util.function.Predicate;
/**
* JSON对象<br>
@ -120,14 +120,14 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
* 如果为普通的JavaBean调用其getters方法getXXX或者isXXX获得值加入到JSON对象<br>
* 例如如果JavaBean对象中有个方法getName()值为"张三"获得的键值对为name: "张三"
*
* @param source JavaBean或者Map对象或者String
* @param config JSON配置文件{@code null}则使用默认配置
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤
* @param source JavaBean或者Map对象或者String
* @param config JSON配置文件{@code null}则使用默认配置
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
* @since 5.8.0
*/
public JSONObject(final Object source, final JSONConfig config, final Filter<MutableEntry<String, Object>> filter) {
public JSONObject(final Object source, final JSONConfig config, final Predicate<MutableEntry<String, Object>> predicate) {
this(DEFAULT_CAPACITY, config);
ObjectMapper.of(source).map(this, filter);
ObjectMapper.of(source).map(this, predicate);
}
// -------------------------------------------------------------------------------------------------------------------- Constructor end
@ -215,15 +215,15 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
/**
* 一次性Put 键值对如果key已经存在抛出异常如果键值中有null值忽略
*
* @param key
* @param value 值对象可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤
* @param key
* @param value 值对象可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
* @return this
* @throws JSONException 值是无穷数字键重复抛出异常
* @since 5.8.0
*/
public JSONObject setOnce(final String key, final Object value, final Filter<MutableEntry<String, Object>> filter) throws JSONException {
put(key, value, filter, true);
public JSONObject setOnce(final String key, final Object value, final Predicate<MutableEntry<String, Object>> predicate) throws JSONException {
put(key, value, predicate, true);
return this;
}
@ -232,14 +232,14 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
*
* @param key
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
* @param checkDuplicate 是否检查重复键如果为{@code true}则出现重复键时抛出{@link JSONException}异常
* @return this.
* @throws JSONException 值是无穷数字抛出此异常
* @since 5.8.0
*/
public JSONObject set(final String key, final Object value, final Filter<MutableEntry<String, Object>> filter, final boolean checkDuplicate) throws JSONException {
put(key, value, filter, checkDuplicate);
public JSONObject set(final String key, final Object value, final Predicate<MutableEntry<String, Object>> predicate, final boolean checkDuplicate) throws JSONException {
put(key, value, predicate, checkDuplicate);
return this;
}
@ -336,14 +336,14 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
* 支持过滤器即选择哪些字段或值不写出
*
* @param indentFactor 每层缩进空格数
* @param filter 过滤器同时可以修改编辑键和值
* @param predicate 过滤器同时可以修改编辑键和值{@link Predicate#test(Object)}{@code true}保留
* @return JSON字符串
* @since 5.7.15
*/
public String toJSONString(final int indentFactor, final Filter<MutableEntry<String, Object>> filter) {
public String toJSONString(final int indentFactor, final Predicate<MutableEntry<String, Object>> predicate) {
final StringWriter sw = new StringWriter();
synchronized (sw.getBuffer()) {
return this.write(sw, indentFactor, 0, filter).toString();
return this.write(sw, indentFactor, 0, predicate).toString();
}
}
@ -359,18 +359,18 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
* @param writer writer
* @param indentFactor 缩进因子定义每一级别增加的缩进量
* @param indent 本级别缩进量
* @param filter 过滤器同时可以修改编辑键和值
* @param predicate 过滤器同时可以修改编辑键和值
* @return Writer
* @throws JSONException JSON相关异常
* @since 5.7.15
*/
public Writer write(final Writer writer, final int indentFactor, final int indent, final Filter<MutableEntry<String, Object>> filter) throws JSONException {
public Writer write(final Writer writer, final int indentFactor, final int indent, final Predicate<MutableEntry<String, Object>> predicate) throws JSONException {
final JSONWriter jsonWriter = JSONWriter.of(writer, indentFactor, indent, config)
.beginObj();
this.forEach((key, value) -> {
if (null != filter) {
if (null != predicate) {
final MutableEntry<String, Object> pair = new MutableEntry<>(key, value);
if (filter.accept(pair)) {
if (predicate.test(pair)) {
// 使用修改后的键值对
jsonWriter.writeField(pair.getKey(), pair.getValue());
}
@ -395,21 +395,21 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
*
* @param key
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
* @param checkDuplicate 是否检查重复键如果为{@code true}则出现重复键时抛出{@link JSONException}异常
* @return 旧值
* @throws JSONException 值是无穷数字抛出此异常
* @since 5.8.0
*/
private Object put(String key, Object value, final Filter<MutableEntry<String, Object>> filter, final boolean checkDuplicate) throws JSONException {
private Object put(String key, Object value, final Predicate<MutableEntry<String, Object>> predicate, final boolean checkDuplicate) throws JSONException {
if (null == key) {
return null;
}
// 添加前置过滤通过MutablePair实现过滤修改键值对等
if (null != filter) {
if (null != predicate) {
final MutableEntry<String, Object> pair = new MutableEntry<>(key, value);
if (filter.accept(pair)) {
if (predicate.test(pair)) {
// 使用修改后的键值对
key = pair.getKey();
value = pair.getValue();

View File

@ -1,9 +1,10 @@
package cn.hutool.json;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.lang.mutable.Mutable;
import cn.hutool.core.lang.mutable.MutableEntry;
import java.util.function.Predicate;
/**
* JSON字符串解析器
*
@ -39,9 +40,9 @@ public class JSONParser {
* 解析{@link JSONTokener}中的字符到目标的{@link JSONObject}
*
* @param jsonObject {@link JSONObject}
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
*/
public void parseTo(final JSONObject jsonObject, final Filter<MutableEntry<String, Object>> filter) {
public void parseTo(final JSONObject jsonObject, final Predicate<MutableEntry<String, Object>> predicate) {
final JSONTokener tokener = this.tokener;
char c;
@ -69,7 +70,7 @@ public class JSONParser {
throw tokener.syntaxError("Expected a ':' after a key");
}
jsonObject.setOnce(key, tokener.nextValue(), filter);
jsonObject.setOnce(key, tokener.nextValue(), predicate);
// Pairs are separated by ','.
@ -95,9 +96,9 @@ public class JSONParser {
* 解析JSON字符串到{@link JSONArray}
*
* @param jsonArray {@link JSONArray}
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null} 表示不过滤
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null} 表示不过滤{@link Predicate#test(Object)}{@code true}保留
*/
public void parseTo(final JSONArray jsonArray, final Filter<Mutable<Object>> filter) {
public void parseTo(final JSONArray jsonArray, final Predicate<Mutable<Object>> predicate) {
final JSONTokener x = this.tokener;
if (x.nextClean() != '[') {
@ -108,10 +109,10 @@ public class JSONParser {
for (; ; ) {
if (x.nextClean() == ',') {
x.back();
jsonArray.addRaw(null, filter);
jsonArray.addRaw(null, predicate);
} else {
x.back();
jsonArray.addRaw(x.nextValue(), filter);
jsonArray.addRaw(x.nextValue(), predicate);
}
switch (x.nextClean()) {
case ',':

View File

@ -5,12 +5,11 @@ import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.iter.ArrayIter;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.lang.mutable.Mutable;
import cn.hutool.core.lang.mutable.MutableEntry;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.reflect.TypeUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.serialize.GlobalSerializeMapping;
import cn.hutool.json.serialize.JSONObjectSerializer;
import cn.hutool.json.serialize.JSONSerializer;
@ -21,6 +20,7 @@ import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.function.Predicate;
/**
* 对象和JSON映射器用于转换对象为JSON支持
@ -65,10 +65,10 @@ public class ObjectMapper {
* 将给定对象转换为{@link JSONObject}
*
* @param jsonObject 目标{@link JSONObject}
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@link Predicate#test(Object)}{@code true}保留
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public void map(final JSONObject jsonObject, final Filter<MutableEntry<String, Object>> filter) {
public void map(final JSONObject jsonObject, final Predicate<MutableEntry<String, Object>> predicate) {
final Object source = this.source;
if (null == source) {
return;
@ -89,29 +89,29 @@ public class ObjectMapper {
if (source instanceof Map) {
// Map
for (final Map.Entry<?, ?> e : ((Map<?, ?>) source).entrySet()) {
jsonObject.set(Convert.toStr(e.getKey()), e.getValue(), filter, false);
jsonObject.set(Convert.toStr(e.getKey()), e.getValue(), predicate, false);
}
} else if (source instanceof Map.Entry) {
final Map.Entry entry = (Map.Entry) source;
jsonObject.set(Convert.toStr(entry.getKey()), entry.getValue(), filter, false);
jsonObject.set(Convert.toStr(entry.getKey()), entry.getValue(), predicate, false);
} else if (source instanceof CharSequence) {
// 可能为JSON字符串
mapFromStr((CharSequence) source, jsonObject, filter);
mapFromStr((CharSequence) source, jsonObject, predicate);
} else if (source instanceof Reader) {
mapFromTokener(new JSONTokener((Reader) source, jsonObject.getConfig()), jsonObject, filter);
mapFromTokener(new JSONTokener((Reader) source, jsonObject.getConfig()), jsonObject, predicate);
} else if (source instanceof InputStream) {
mapFromTokener(new JSONTokener((InputStream) source, jsonObject.getConfig()), jsonObject, filter);
mapFromTokener(new JSONTokener((InputStream) source, jsonObject.getConfig()), jsonObject, predicate);
} else if (source instanceof byte[]) {
mapFromTokener(new JSONTokener(IoUtil.toStream((byte[]) source), jsonObject.getConfig()), jsonObject, filter);
mapFromTokener(new JSONTokener(IoUtil.toStream((byte[]) source), jsonObject.getConfig()), jsonObject, predicate);
} else if (source instanceof JSONTokener) {
// JSONTokener
mapFromTokener((JSONTokener) source, jsonObject, filter);
mapFromTokener((JSONTokener) source, jsonObject, predicate);
} else if (source instanceof ResourceBundle) {
// JSONTokener
mapFromResourceBundle((ResourceBundle) source, jsonObject, filter);
mapFromResourceBundle((ResourceBundle) source, jsonObject, predicate);
} else if (BeanUtil.isReadableBean(source.getClass())) {
// 普通Bean
mapFromBean(source, jsonObject, filter);
mapFromBean(source, jsonObject, predicate);
} else {
// 不支持对象类型转换为JSONObject
throw new JSONException("Unsupported type [{}] to JSONObject!", source.getClass());
@ -122,11 +122,11 @@ public class ObjectMapper {
* 将给定对象转换为{@link JSONArray}
*
* @param jsonArray 目标{@link JSONArray}
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
* @throws JSONException 非数组或集合
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public void map(final JSONArray jsonArray, final Filter<Mutable<Object>> filter) throws JSONException {
public void map(final JSONArray jsonArray, final Predicate<Mutable<Object>> predicate) throws JSONException {
final Object source = this.source;
if (null == source) {
return;
@ -138,15 +138,15 @@ public class ObjectMapper {
serializer.serialize(jsonArray, source);
} else if (source instanceof CharSequence) {
// JSON字符串
mapFromStr((CharSequence) source, jsonArray, filter);
mapFromStr((CharSequence) source, jsonArray, predicate);
} else if (source instanceof Reader) {
mapFromTokener(new JSONTokener((Reader) source, jsonArray.getConfig()), jsonArray, filter);
mapFromTokener(new JSONTokener((Reader) source, jsonArray.getConfig()), jsonArray, predicate);
} else if (source instanceof InputStream) {
mapFromTokener(new JSONTokener((InputStream) source, jsonArray.getConfig()), jsonArray, filter);
mapFromTokener(new JSONTokener((InputStream) source, jsonArray.getConfig()), jsonArray, predicate);
} else if (source instanceof byte[]) {
final byte[] bytesSource = (byte[]) source;
if ('[' == bytesSource[0] && ']' == bytesSource[bytesSource.length - 1]) {
mapFromTokener(new JSONTokener(IoUtil.toStream(bytesSource), jsonArray.getConfig()), jsonArray, filter);
mapFromTokener(new JSONTokener(IoUtil.toStream(bytesSource), jsonArray.getConfig()), jsonArray, predicate);
} else {
// https://github.com/dromara/hutool/issues/2369
// 非标准的二进制流则按照普通数组对待
@ -155,7 +155,7 @@ public class ObjectMapper {
}
}
} else if (source instanceof JSONTokener) {
mapFromTokener((JSONTokener) source, jsonArray, filter);
mapFromTokener((JSONTokener) source, jsonArray, predicate);
} else {
final Iterator<?> iter;
if (ArrayUtil.isArray(source)) {// 数组
@ -174,7 +174,7 @@ public class ObjectMapper {
next = iter.next();
// 检查循环引用
if (next != source) {
jsonArray.addRaw(JSONUtil.wrap(next, config), filter);
jsonArray.addRaw(JSONUtil.wrap(next, config), predicate);
}
}
}
@ -185,15 +185,15 @@ public class ObjectMapper {
*
* @param bundle ResourceBundle
* @param jsonObject {@link JSONObject}
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
* @since 5.3.1
*/
private static void mapFromResourceBundle(final ResourceBundle bundle, final JSONObject jsonObject, final Filter<MutableEntry<String, Object>> filter) {
private static void mapFromResourceBundle(final ResourceBundle bundle, final JSONObject jsonObject, final Predicate<MutableEntry<String, Object>> predicate) {
final Enumeration<String> keys = bundle.getKeys();
while (keys.hasMoreElements()) {
final String key = keys.nextElement();
if (key != null) {
InternalJSONUtil.propertyPut(jsonObject, key, bundle.getString(key), filter);
InternalJSONUtil.propertyPut(jsonObject, key, bundle.getString(key), predicate);
}
}
}
@ -203,16 +203,16 @@ public class ObjectMapper {
*
* @param source JSON字符串
* @param jsonObject {@link JSONObject}
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
*/
private static void mapFromStr(final CharSequence source, final JSONObject jsonObject, final Filter<MutableEntry<String, Object>> filter) {
private static void mapFromStr(final CharSequence source, final JSONObject jsonObject, final Predicate<MutableEntry<String, Object>> predicate) {
final String jsonStr = StrUtil.trim(source);
if (StrUtil.startWith(jsonStr, '<')) {
// 可能为XML
XML.toJSONObject(jsonObject, jsonStr, false);
return;
}
mapFromTokener(new JSONTokener(StrUtil.trim(source), jsonObject.getConfig()), jsonObject, filter);
mapFromTokener(new JSONTokener(StrUtil.trim(source), jsonObject.getConfig()), jsonObject, predicate);
}
/**
@ -220,11 +220,11 @@ public class ObjectMapper {
*
* @param source JSON字符串
* @param jsonArray {@link JSONArray}
* @param filter 值过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤
* @param predicate 值过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
*/
private void mapFromStr(final CharSequence source, final JSONArray jsonArray, final Filter<Mutable<Object>> filter) {
private void mapFromStr(final CharSequence source, final JSONArray jsonArray, final Predicate<Mutable<Object>> predicate) {
if (null != source) {
mapFromTokener(new JSONTokener(StrUtil.trim(source), jsonArray.getConfig()), jsonArray, filter);
mapFromTokener(new JSONTokener(StrUtil.trim(source), jsonArray.getConfig()), jsonArray, predicate);
}
}
@ -233,10 +233,10 @@ public class ObjectMapper {
*
* @param x JSONTokener
* @param jsonObject {@link JSONObject}
* @param filter 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@link Predicate#test(Object)}{@code true}保留
*/
private static void mapFromTokener(final JSONTokener x, final JSONObject jsonObject, final Filter<MutableEntry<String, Object>> filter) {
JSONParser.of(x).parseTo(jsonObject, filter);
private static void mapFromTokener(final JSONTokener x, final JSONObject jsonObject, final Predicate<MutableEntry<String, Object>> predicate) {
JSONParser.of(x).parseTo(jsonObject, predicate);
}
/**
@ -244,22 +244,23 @@ public class ObjectMapper {
*
* @param x {@link JSONTokener}
* @param jsonArray {@link JSONArray}
* @param filter 值过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤
* @param predicate 值过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
*/
private static void mapFromTokener(final JSONTokener x, final JSONArray jsonArray, final Filter<Mutable<Object>> filter) {
JSONParser.of(x).parseTo(jsonArray, filter);
private static void mapFromTokener(final JSONTokener x, final JSONArray jsonArray, final Predicate<Mutable<Object>> predicate) {
JSONParser.of(x).parseTo(jsonArray, predicate);
}
/**
* 从Bean转换
*
* @param bean Bean对象
* @param predicate 过滤器{@link Predicate#test(Object)}{@code true}保留null表示保留
* @param jsonObject {@link JSONObject}
*/
private static void mapFromBean(final Object bean, final JSONObject jsonObject, final Filter<MutableEntry<String, Object>> filter) {
private static void mapFromBean(final Object bean, final JSONObject jsonObject, final Predicate<MutableEntry<String, Object>> predicate) {
final CopyOptions copyOptions = InternalJSONUtil.toCopyOptions(jsonObject.getConfig());
if (null != filter) {
copyOptions.setFieldEditor((entry -> filter.accept(entry) ? entry : null));
if (null != predicate) {
copyOptions.setFieldEditor((entry -> predicate.test(entry) ? entry : null));
}
BeanUtil.beanToMap(bean, jsonObject, copyOptions);
}

View File

@ -1,9 +1,9 @@
package cn.hutool.poi.excel.sax.handler;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Func1;
import java.util.List;
import java.util.function.Function;
/**
* 抽象行数据处理器通过实现{@link #handle(int, long, List)} 处理原始数据<br>
@ -26,7 +26,7 @@ public abstract class AbstractRowHandler<T> implements RowHandler {
/**
* 行数据转换函数
*/
protected Func1<List<Object>, T> convertFunc;
protected Function<List<Object>, T> convertFunc;
/**
* 构造
@ -45,7 +45,7 @@ public abstract class AbstractRowHandler<T> implements RowHandler {
if (rowIndex < this.startRowIndex || rowIndex > this.endRowIndex) {
return;
}
handleData(sheetIndex, rowIndex, convertFunc.callWithRuntimeException(rowCells));
handleData(sheetIndex, rowIndex, convertFunc.apply(rowCells));
}
/**