工具类
ZhLambdaUtils
@SuppressWarnings("all")
public class ZhLambdaUtils {
/**
* METHOD_NAME
*/
private static final String METHOD_NAME = "writeReplace";
/**
* 获取到lambda参数的方法名称
*
* @param <T> parameter
* @param function function
* @return the name
* @since 2023.1.1
*/
public static <T> String getLambdaMethodName(FilterUtils.ZhFunction<T, ?> function) {
try {
return ((SerializedLambda) MethodUtils.invokeMethod(function, true, METHOD_NAME)).getImplMethodName();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Method to property
*
* @param name name
* @return the string
* @since 2023.1.1
*/
public static String methodToProperty(String name) {
if (name.startsWith("is")) {
name = name.substring(2);
} else {
if (!name.startsWith("get") && !name.startsWith("set")) {
throw new IllegalArgumentException("Error parsing property name '" + name + "'. Didn't start with 'is', 'get' or 'set'.");
}
name = name.substring(3);
}
if (name.length() == 1 || name.length() > 1 && !Character.isUpperCase(name.charAt(1))) {
name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
}
return name;
}
/**
* Is property
*
* @param name name
* @return the boolean
* @since 2023.1.1
*/
public static boolean isProperty(String name) {
return isGetter(name) || isSetter(name);
}
/**
* Is getter
*
* @param name name
* @return the boolean
* @since 2023.1.1
*/
public static boolean isGetter(String name) {
return name.startsWith("get") && name.length() > 3 || name.startsWith("is") && name.length() > 2;
}
/**
* Is setter
*
* @param name name
* @return the boolean
* @since 2023.1.1
*/
public static boolean isSetter(String name) {
return name.startsWith("set") && name.length() > 3;
}
}
SelectSubsetUtils
该工具类可以实现通过对象的指定字段实现双向遍历
/**
* 通过本级唯一key值,以及本级字段、父级字段迭查询所有本级的子集
*/
@UtilityClass
public class SelectSubsetUtils {
/**
* Filter
*
* @param <D> parameter
* @param origin 需要被过滤的数据集
* @param left 本级唯一key -例如code
* @param right 本级与父级关联key值 -例如parentCode
* @param adjust 本级唯一key值过滤条件
* @return the list
* @since 2023.1.1
*/
public static <D> List<D> filterSon(List<D> origin, ZhFunction<D, ?> left, ZhFunction<D, ?> right, Adjust adjust) {
return filter(origin, left, right, adjust, false);
}
/**
* Filter parent
*
* @param <D> parameter
* @param origin 需要被过滤的数据集
* @param left 本级唯一key -例如code
* @param right 本级与父级关联key值 -例如parentCode
* @param adjust 本级唯一key值过滤条件
* @return the list
* @since 2023.1.1
*/
public static <D> List<D> filterParent(List<D> origin, ZhFunction<D, ?> left, ZhFunction<D, ?> right, Adjust adjust) {
return filter(origin, left, right, adjust, true);
}
/**
* Filter
*
* @param <D> parameter
* @param origin origin
* @param left left
* @param right right
* @param adjust adjust
* @param reverset reverset
* @return the list
* @since 2023.1.1
*/
private static <D> List<D> filter(List<D> origin, ZhFunction<D, ?> left, ZhFunction<D, ?> right,
Adjust adjust, Boolean reverset) {
//过滤全量数据按照本级唯一key进行过滤
List<D> ds = origin.stream()
.filter(o -> {
//通过反射获取到传递进来的本级唯一key值
Object value = getObject(left, o);
return adjust.test(value);
}).collect(Collectors.toList());
//调用与父级关联的key值进行递归过滤
if (reverset) {
// 如果是反转,那么就是父级过滤
return filter(origin, ds, left, right);
} else {
// 如果是正常,那么就是子级过滤
return filter(origin, ds, right, left);
}
}
/**
* Filter
*
* @param <D> parameter
* @param origin 需要被过滤的数据源
* @param filter 被过滤后的数据集
* @param left 本级唯一key -例如code
* @param right 本级与父级关联key值 -例如parentCode
* @return the list
* @since 2023.1.1
*/
private static <D> List<D> filter(List<D> origin, List<D> filter, ZhFunction<D, ?> left, ZhFunction<D, ?> right) {
//构建本级过滤的数据,然后拿出来跟全量数据再次进行比对
List<D> list = new LinkedList<>(filter);
if (CollectionUtils.isEmpty(filter)) {
return list;
}
//遍历过滤后的数据集
filter.forEach(f -> {
//跟全量的数据进行比较
List<D> ds = origin.stream()
.filter(o -> {
//将全量的数据和过滤出的数据进行比较,找出后续的子节点
Object value = getObject(left, o);
Object value2 = getObject(right, f);
return value.equals(value2);
}).collect(Collectors.toList());
if (CollectionUtils.isEmpty(ds)) {
return;
}
//递归调用
list.addAll(filter(origin, ds, left, right));
});
return list;
}
/**
* 获取值
*
* @param <D> parameter
* @param firstFiled first filed
* @param d d
* @return object object
* @since 2023.1.1
*/
private static <D> Object getObject(ZhFunction<D, ?> firstFiled, D d) {
String lambdaMethodName = ZhLambdaUtils.getLambdaMethodName(firstFiled);
//获取到字段名称
String fieldName = ZhLambdaUtils.methodToProperty(lambdaMethodName);
Object value = null;
try {
Field field = FieldUtils.getDeclaredField(d.getClass(), fieldName, true);
value = field.get(d);
} catch (Exception e) {
throw new RuntimeException(e);
}
return value;
}
/**
* 自定义判断函数
*/
@FunctionalInterface
public interface Adjust {
/**
* Test
*
* @param value value
* @return the boolean
* @since 2023.1.1
*/
boolean test(Object value);
}
/**
* 自定义 Serializable 函数接口,这个接口有大用,至于为什么可以看下面参考博客
*/
@FunctionalInterface
public interface ZhFunction<T, R> extends Function<T, R>, Serializable {
}
}
测试
寻找字段 Code 为 1681497872765722624,并且关联的父级code为 ParentCode 的所有子集
public static void main(String[] args) {
List<A> list = new ArrayList<>();
A a = new A("1", "1681497872765722624");
A a2 = new A("1681497872765722624", "1681498005196677120");
A a3 = new A("1681497872765722624", "1681498062989991936");
A a4 = new A("1681497872765722624", "1681498151091347456");
A a5 = new A("1681498151091347456", "2");
A a6 = new A("1681498151091347456", "3");
A a7 = new A("8", "7");
A a8 = new A("", "8");
list.add(a);
list.add(a2);
list.add(a3);
list.add(a4);
list.add(a5);
list.add(a6);
list.add(a7);
list.add(a8);
List<A> target = filter(list, A::getCode, A::getParentCode, "1681497872765722624"::equals);
target.forEach(System.out::println);
}
参考文档:
函数接口实现Serializable的用处说明