这几天做了一个项目,需要根据多个属性分组,这里分组的属性不确定,可能是1个,也可能是好几个。这里在网上找的大部分都是根据固定多个属性去分组,满足不了需求,这个方法比较适用于 使用者不确定 要分组的字段是什么,比如说要分组的字段存在表里,需要查出来,然后再根据查出来的字段分组,所以不知道要分组的字段是什么,这里用了10几分钟,写了一个动态多属性分组,这里 只放出第一版代码,使用者需要改动,自己去调整。
这里使用java8 函数式接口 和反射 去分组
//这里是获取对象的get方法
private static List getReadMethod(List l, Object o) {
List list = new ArrayList<>();
Class oo = o.getClass();
for (int i = 0; i < l.size(); i++) {
try {
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(l.get(i), oo);
Method readMethod = propertyDescriptor.getReadMethod();
list.add(readMethod);
} catch (Exception e) {
e.printStackTrace();
}
}
return list;
}
//这里是 方法入口,调用这个方法就行
public static <T, R> Map<String, List<T>> groupingByDynamicProperties(Object o, List<T> list, List<String> listProperties) {
List<Method> readMethod = getReadMethod(listProperties, o);
return list.stream().collect(Collectors.groupingBy(t -> groupingByDynamicPropertiesTwo(t, readMethod)));
}
//获取流中每个对象的 属性值
public static <T, R> String groupingByDynamicPropertiesTwo(T t, List<Method> readMethods) {
if (readMethods == null || readMethods.size() == 0) {
throw new NullPointerException("functions数组不可以为空");
} else if (readMethods.size() == 1) {
if (readMethods.get(0) == null) {
return null;
}
try {
return readMethods.get(0).invoke(t).toString();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} else {
return readMethods.stream().map(fun -> {
try {
if (fun.invoke(t) != null) {
return fun.invoke(t).toString();
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}).reduce((str1, str2) -> str1 + "|" + str2).get();
}
return null;
}
在这里插入图片描述
这里是自己测试 之后的结构, 第一个参数 传一个对象用于获取get方法,第二个属性传需要分组的list,第三个属性传 属性值的 list