使用泛型和函数式接口实现enum枚举类的通用匹配方法

业务上很多时候枚举类有转换匹配的需求,如果是在每个枚举类中手动去实现匹配,工作量比较大,也不能复用。

以下方法通过应用泛型和函数式接口,可以支持所有枚举类通过某一个字段匹配一个或多个枚举实例及其字段值,无需在每个枚举类单独写匹配方法了,方便很多,只依赖于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 {}

}

运行效果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值