List泛型查找目标值的工具类,支持2种查找(一个查找对应的对象,一个查找对应对象的属性的值。)也分布对应2种方法(一个基于方法和一个属性)。
ListFindUtils.java
package com.imddy.tweb.utils;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class ListFindUtils {
private static final Logger log = LoggerFactory.getLogger(ListFindUtils.class);
// 缓存反射得到的方法和字段,以提高性能
private static final ThreadLocal<Map<Class<?>, Map<String, Method>>> methodCache = ThreadLocal.withInitial(HashMap::new);
private static final ThreadLocal<Map<Class<?>, Map<String, Field>>> fieldCache = ThreadLocal.withInitial(HashMap::new);
/**
* 根据方法名查找对象,并返回匹配对象的另一属性值。
*/
public static <T, R, V> V findObjectByMethod(Object targetObjectValue, String getterMethodName, String returnGetterMethodName, List<T> objectList, Class<T> tClass) {
Method getterMethod = getMethod(tClass, getterMethodName);
Method returnGetterMethod = getMethod(tClass, returnGetterMethodName);
if (getterMethod == null || returnGetterMethod == null) {
log.error("Methods not found.");
return null;
}
try {
for (T t : objectList) {
Object object1 = getterMethod.invoke(t);
if (Objects.equals(targetObjectValue, object1)) {
return (V) returnGetterMethod.invoke(t);
}
}
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("Error invoking methods.", e);
}
return null;
}
/**
* 通过字段查找对象,并返回匹配对象的另一字段值。
*/
public static <T, R> R findObjectByField(Object targetObjectValue, String fieldName, String returnFieldName, List<T> objectList, Class<T> tClass) {
Field field = getField(tClass, fieldName);
Field returnField = getField(tClass, returnFieldName);
if (field == null || returnField == null) {
log.error("Fields not found.");
return null;
}
try {
for (T t : objectList) {
field.setAccessible(true);
Object object1 = field.get(t);
if (Objects.equals(targetObjectValue, object1)) {
returnField.setAccessible(true);
return (R) returnField.get(t);
}
}
} catch (IllegalAccessException e) {
log.error("Error accessing fields.", e);
}
return null;
}
/**
* 根据方法名查找对象并返回。
*/
public static <T, R> T findByMethod(Object targetObjectValue, String methodName, List<T> objectList, Class<T> tClass) {
Method method = getMethod(tClass, methodName);
if (method == null) {
log.error("Method not found.");
return null;
}
try {
for (T t : objectList) {
Object value = method.invoke(t);
if (Objects.equals(value, targetObjectValue)) {
return t;
}
}
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("Error invoking method.", e);
}
return null;
}
/**
* 通过字段查找对象并返回。
*/
public static <T> T findByField(Object targetObjectValue, String fieldName, List<T> objectList, Class<T> tClass) {
Field field = getField(tClass, fieldName);
if (field == null) {
log.error("Field not found.");
return null;
}
try {
for (T t : objectList) {
field.setAccessible(true);
Object value = field.get(t);
if (Objects.equals(value, targetObjectValue)) {
return t;
}
}
} catch (IllegalAccessException e) {
log.error("Error accessing field.", e);
}
return null;
}
private static Method getMethod(Class<?> clazz, String methodName) {
Map<String, Method> cache = methodCache.get().computeIfAbsent(clazz, k -> new HashMap<>());
return cache.computeIfAbsent(methodName, name -> {
try {
return clazz.getMethod(name);
} catch (NoSuchMethodException e) {
log.error("Method {} not found in class {}", name, clazz.getName());
return null;
}
});
}
private static Field getField(Class<?> clazz, String fieldName) {
Map<String, Field> cache = fieldCache.get().computeIfAbsent(clazz, k -> new HashMap<>());
return cache.computeIfAbsent(fieldName, name -> {
try {
return clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
log.error("Field {} not found in class {}", name, clazz.getName());
return null;
}
});
}
public void test001() throws NoSuchFieldException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
List<TtVo> ttVoList = new ArrayList<>();
TtVo ttVo1 = new TtVo();
ttVo1.setId(1);
ttVo1.setPai("first Name");
ttVoList.add(ttVo1);
TtVo ttVo2 = new TtVo();
ttVo2.setId(2);
ttVo2.setPai("Name Second");
ttVoList.add(ttVo2);
TtVo ttVo3 = new TtVo();
ttVo3.setId(3);
ttVo3.setPai("张三");
ttVoList.add(ttVo3);
TtVo ttVo4 = new TtVo();
ttVo4.setId(4);
ttVo4.setPai("麻四");
ttVoList.add(ttVo4);
TtVo ttVo5 = new TtVo();
ttVo5.setId(5);
ttVo5.setPai("five Name");
ttVoList.add(ttVo5);
TtVo ttVo301 = new TtVo();
ttVo301.setId(301);
ttVo301.setPai("three thrad one! ");
ttVoList.add(ttVo301);
TtVo ttVo302 = new TtVo();
ttVo302.setId(302);
ttVo302.setPai("three 302 xxx! ");
ttVoList.add(ttVo302);
TtVo ttVo303 = new TtVo();
ttVo303.setId(303);
ttVo303.setPai("five303Name");
ttVoList.add(ttVo303);
Object s1 = ListFindUtils.findObjectByMethod("five Name", "getPai", "getId", ttVoList, TtVo.class);
log.info("s1: " + s1 );
Object s2 = ListFindUtils.findObjectByMethod(3, "getId", "getPai", ttVoList, TtVo.class);
log.info("s2: " + s2 );
Object s3 = ListFindUtils.findObjectByMethod("麻四", "getPai", "getId", ttVoList, TtVo.class);
log.info("s3: " + s3 );
Object s4 = ListFindUtils.findObjectByField("five Name", "pai", "id", ttVoList, TtVo.class);
log.info("s4: " + s4 );
Object s5 = ListFindUtils.findObjectByField(3, "id", "pai", ttVoList, TtVo.class);
log.info("s5: " + s5 );
Object s6 = ListFindUtils.findObjectByField("麻四", "pai", "id", ttVoList, TtVo.class);
log.info("s6: " + s6 );
Object s7 = ListFindUtils.findByMethod(1, "getId", ttVoList, TtVo.class);
log.info("s7: " + s7 );
Object s8 = ListFindUtils.findByMethod(5, "getId", ttVoList, TtVo.class);
log.info("s8: " + s8 );
Object s9 = ListFindUtils.findByMethod("张三", "getPai", ttVoList, TtVo.class);
log.info("s9: " + s9 );
Object s10 = ListFindUtils.findByMethod("麻四", "getPai", ttVoList, TtVo.class);
log.info("s10: " + s10 );
Object s11 = ListFindUtils.findByField(1, "id", ttVoList, TtVo.class);
log.info("s11: " + s11 );
Object s12 = ListFindUtils.findByField(5, "id", ttVoList, TtVo.class);
log.info("s12: " + s12 );
Object s13 = ListFindUtils.findByField("张三", "pai", ttVoList, TtVo.class);
log.info("s13: " + s13 );
Object s14 = ListFindUtils.findByField("麻四", "pai", ttVoList, TtVo.class);
log.info("s14: " + s14 );
log.info("-------------------------------------------------------------------------------------");
Object s21 = ListFindUtils.findObjectByMethod("five303Name", "getPai", "getId", ttVoList, TtVo.class);
log.info("s21: " + s21 );
Object s22 = ListFindUtils.findObjectByMethod(303, "getId", "getPai", ttVoList, TtVo.class);
log.info("s22: " + s22 );
Object s23 = ListFindUtils.findObjectByMethod("three 302 xxx! ", "getPai", "getId", ttVoList, TtVo.class);
log.info("s23: " + s23 );
Object s24 = ListFindUtils.findObjectByField("five303Name", "pai", "id", ttVoList, TtVo.class);
log.info("s24: " + s24 );
Object s25 = ListFindUtils.findObjectByField(303, "id", "pai", ttVoList, TtVo.class);
log.info("s25: " + s25 );
Object s26 = ListFindUtils.findObjectByField("three 302 xxx! ", "pai", "id", ttVoList, TtVo.class);
log.info("s26: " + s26 );
Object s27 = ListFindUtils.findByMethod(303, "getId", ttVoList, TtVo.class);
log.info("s27: " + s27 );
Object s28 = ListFindUtils.findByMethod(301, "getId", ttVoList, TtVo.class);
log.info("s28: " + s28 );
Object s29 = ListFindUtils.findByMethod("张三", "getPai", ttVoList, TtVo.class);
log.info("s29: " + s29 );
Object s30 = ListFindUtils.findByMethod("three 302 xxx! ", "getPai", ttVoList, TtVo.class);
log.info("s30: " + s30 );
Object s31 = ListFindUtils.findByField(303, "id", ttVoList, TtVo.class);
log.info("s31: " + s31 );
Object s32 = ListFindUtils.findByField(301, "id", ttVoList, TtVo.class);
log.info("s32: " + s32 );
Object s33 = ListFindUtils.findByField("张三", "pai", ttVoList, TtVo.class);
log.info("s33: " + s33 );
Object s34 = ListFindUtils.findByField("three 302 xxx! ", "pai", ttVoList, TtVo.class);
log.info("s34: " + s34 );
}
@Data
class TtVo {
private Integer id;
private String pai;
}
public static void main(String[] args) throws NoSuchFieldException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
new ListFindUtils().test001();
}
}