业务上很多时候枚举类有转换匹配的需求,如果是在每个枚举类中手动去实现匹配,工作量比较大,也不能复用。
以下方法通过应用泛型和函数式接口,可以支持所有枚举类通过某一个字段匹配一个或多个枚举实例及其字段值,无需在每个枚举类单独写匹配方法了,方便很多,只依赖于jdk实现,无需引入其他依赖。
package com.tsd.dlmPlatform_common.util;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
*
* @author HeJun
* @date 2024年9月3日
* @Version V1.4
* @Description Enum匹配工具类
*
*/
public class EnumMatchUtil {
public static <T extends Enum> T getEnumByFunc(SFunction<T,?> matchGetFunc, Object matchValue) {
T targetEnum = null;
if(matchValue != null) {
Class<T> enumClazz = getInstantiatedClass(matchGetFunc);
T[] enumConstants = enumClazz.getEnumConstants();
if(enumConstants != null) {
for (T enumConstant : enumConstants) {
Object apply = matchGetFunc.apply(enumConstant);
if(matchValue.equals(apply)) {
targetEnum = enumConstant;
break;
}
}
}
}
return targetEnum;
}
public static <T extends Enum, R> R getEnumFieldByFunc(SFunction<T,?> matchGetFunc, Object matchValue, SFunction<T,R> fieldGetFunc) {
R value = null;
T enumByFunc = getEnumByFunc(matchGetFunc, matchValue);
if(enumByFunc != null) {
value = fieldGetFunc.apply(enumByFunc);
}
return value;
}
public static <T extends Enum> List<T> getAllEnumByFunc(SFunction<T,?> matchGetFunc, List<?> matchValues) {
List<T> list = new ArrayList<>();
Class<T> enumClazz = getInstantiatedClass(matchGetFunc);
T[] enumConstants = enumClazz.getEnumConstants();
Map<?, List<T>> collect = Stream.of(enumConstants).collect(Collectors.groupingBy(matchGetFunc));
if(!collect.isEmpty() && matchValues != null) {
for (Object value : matchValues) {
List<T> enums = collect.get(value);
if(enums != null) {
list.addAll(enums);
}
}
}
return list;
}
public static <T extends Enum, R> List<R> getAllEnumFieldByFunc(SFunction<T,?> matchGetFunc, List<?> matchValues, SFunction<T,R> fieldGetFunc) {
List<R> list = new ArrayList<>();
Class<T> enumClazz = getInstantiatedClass(matchGetFunc);
T[] enumConstants = enumClazz.getEnumConstants();
Map<?, Set<R>> collect = Stream.of(enumConstants).collect(Collectors.groupingBy(matchGetFunc, Collectors.mapping(fieldGetFunc, Collectors.toSet())));
if(!collect.isEmpty() && matchValues != null) {
for (Object value : matchValues) {
Set<R> enums = collect.get(value);
if(enums != null){
list.addAll(enums);
}
}
}
return list;
}
private static <T>SerializedLambda getSerializedLambda(SFunction<T,?> propertyFunc) {
// 从function取出序列化方法
Method writeReplaceMethod = null;
try {
writeReplaceMethod = propertyFunc.getClass().getDeclaredMethod("writeReplace");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
SerializedLambda serializedLambda = null;
// 从序列化方法取出序列化的lambda信息
try {
writeReplaceMethod.setAccessible(true);
serializedLambda = (SerializedLambda) writeReplaceMethod.invoke(propertyFunc);
} catch (Exception e) {
throw new RuntimeException(e);
}
return serializedLambda;
}
private static <T>Class<T> getInstantiatedClass(SFunction<T,?> propertyFunc) {
SerializedLambda serializedLambda = getSerializedLambda(propertyFunc);
String instantiatedMethodType = serializedLambda.getInstantiatedMethodType();
String instantiatedType = instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(";")).replace("/", ".");
Class<T> instantiatedClass = null;
try {
instantiatedClass = (Class<T>) Class.forName(instantiatedType, false, propertyFunc.getClass().getClassLoader());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
return instantiatedClass;
}
public interface SFunction<T,R> extends Function<T,R>, Serializable {}
}
运行效果: