java 动态 Lambda
Posted 正怒月神
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 动态 Lambda 相关的知识,希望对你有一定的参考价值。
一,反射类
package com.leadtrans.report.common;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author: Tyler
* @createDate: 2021/12/9
*/
public class ReflectionUtil
/**
* 调用示例
* public ApiResponse<String> test() throws Exception
* Class[] argsType=new Class[]Class.forName("java.lang.String");
* Object[] args=new Object[]"hello";
* ReflectionUtil.invokeMethod(new ReportImpl(),"Test",argsType,args);
* return new ApiResponse().Success("str");
*
* @param owner 类的实例
* @param methodName 方法名
* @param argsClass 参数类型
* @param args 参数
* @return
* @throws Exception
*/
public static Object invokeMethod(Object owner,String methodName,Class[] argsClass,Object[] args) throws Exception
Object objRtn=null;
Class ownerClass = owner.getClass();
Method method = ownerClass.getMethod(methodName, argsClass);
objRtn = method.invoke(owner, args);
return objRtn;
public static Field getFiled(Object obj,String filedName)
Field field=null;
try
field = obj.getClass().getDeclaredField(filedName);
field.setAccessible(true);
catch (NoSuchFieldException e)
e.printStackTrace();
finally
return field;
public static Object getFiledValue(Object obj,String filedName)
Object objValue=null;
try
Field field = getFiled(obj,filedName);
objValue = field.get(obj);
catch (IllegalAccessException e)
e.printStackTrace();
finally
return objValue;
二,动态lambda
/**
* Lambda 动态 Filter
*
* @param list 数据
* @param equalsMap contains 过滤器
* @param notEqualsMap !contains 过滤器
* @param <T>
* @return
*/
public <T> List<T> getDataListFilter(List<T> list, Map<String, List<Object>> equalsMap, Map<String, List<Object>> notEqualsMap)
Supplier<Stream<T>> st = () -> list.stream();
if (equalsMap != null)
for (Map.Entry<String, List<Object>> item : equalsMap.entrySet())
Supplier<Stream<T>> stFilter = st;
st = () -> stFilter.get().filter(x -> item.getValue().contains(ReflectionUtil.getFiledValue(x, item.getKey())));
if (notEqualsMap != null)
for (Map.Entry<String, List<Object>> item : notEqualsMap.entrySet())
Supplier<Stream<T>> stFilter = st;
st = () -> stFilter.get().filter(x -> !item.getValue().contains(ReflectionUtil.getFiledValue(x, item.getKey())));
List<T> rList = st.get().collect(Collectors.toList());
return rList;
/**
* Lambda 动态 Group
*
* @param list 数据
* @param fieldGroups 聚合字段
* @param <T>
* @return
*/
public <T> Map<String, List<T>> getDataListGroup(List<T> list, List<String> fieldGroups)
Map<String, List<T>> map = list.stream().collect(Collectors.groupingBy(x ->
String groupItem = "";
for (String y : fieldGroups)
groupItem += ReflectionUtil.getFiledValue(x, y) + "_";
return groupItem;
));
return map;
/**
* 输出数据
*
* @param dataList 数据源
* @param fieldNames 属性名
* @param calculateNames 需要计算的列
* @return
*/
public <T> List<List<Object>> getDataList(Map<String, List<T>> dataList, List<String> fieldNames, List<String> calculateNames)
List<List<Object>> data = new ArrayList<>();
for (Map.Entry<String, List<T>> entry : dataList.entrySet())
List<Object> obj = new ArrayList<>();
for (String colName : fieldNames)
//普通字段
if (!calculateNames.contains(colName))
Object colVal = ReflectionUtil.getFiledValue(entry.getValue().get(0), colName);
obj.add(colVal);
//计算count 标签
else if(colName.toLowerCase().replace(" ","").startsWith("count(".toLowerCase()))
String countName=colName.substring("count(".length(),colName.indexOf(")"));
String[] args=countName.split(",");
//如果args>1,说明有条件
if(args.length>1)
//获取多个条件
String[] argsArr=args[0].split("\\\\|");
Supplier<Stream<T>> st =null;
for(String argsSimple : argsArr)
//获取单个条件,拼接
String[] argsKV;
if(argsSimple.indexOf("!:")>0)
//不等
argsKV=argsSimple.split("!:");
st = ()-> entry.getValue().stream()
.filter(x->!(ReflectionUtil.getFiledValue(x, argsKV[0])==null?"null":ReflectionUtil.getFiledValue(x, argsKV[0]).toString()).equals(argsKV[1]));
else
//相等
argsKV = argsSimple.split(":");
st = ()-> entry.getValue().stream()
.filter(x->(ReflectionUtil.getFiledValue(x, argsKV[0])==null?"null":ReflectionUtil.getFiledValue(x, argsKV[0]).toString()).equals(argsKV[1]));
Object colVal = st.get().collect(Collectors.toList()).size();
obj.add(colVal);
else
Object colVal = entry.getValue().size();
obj.add(colVal);
//计算countDistinct标签
else if(colName.toLowerCase().replace(" ","").startsWith("countDistinct(".toLowerCase()))
String countName=colName.substring("countDistinct(".length(),colName.indexOf(")"));
String[] args=countName.split(",");
//如果args>1,说明有条件
if(args.length>1)
//获取多个条件
String[] argsArr=args[0].split("\\\\|");
Supplier<Stream<Object>> st =null;
for(String argsSimple : argsArr)
//获取单个条件,拼接
String[] argsKV;
//不等
if(argsSimple.indexOf("!:")>0)
argsKV = argsSimple.split("!:");
st =()-> entry.getValue().stream()
.filter(x->!(ReflectionUtil.getFiledValue(x, argsKV[0])==null?"null":ReflectionUtil.getFiledValue(x, argsKV[0]).toString()).equals(argsKV[1]))
.map(x->ReflectionUtil.getFiledValue(x, args[1]))
.distinct();
else
//相等
argsKV = argsSimple.split(":");
st =()-> entry.getValue().stream()
.filter(x->(ReflectionUtil.getFiledValue(x, argsKV[0])==null?"null":ReflectionUtil.getFiledValue(x, argsKV[0]).toString()).equals(argsKV[1]))
.map(x->ReflectionUtil.getFiledValue(x, args[1]))
.distinct();
Object colVal = st.get().collect(Collectors.toList()).size();
obj.add(colVal);
else
Object colVal = entry.getValue().stream()
.map(x->ReflectionUtil.getFiledValue(x, args[0]))
.distinct()
.collect(Collectors.toList()).size();
obj.add(colVal);
//计算sum 标签
else if(colName.toLowerCase().replace(" ","").startsWith("sum(".toLowerCase()))
String sumName=colName.substring("sum(".length(),colName.indexOf(")"));
String[] args=sumName.split(",");
//如果args>1,说明有条件
if(args.length>1)
//获取多个条件
String[] argsArr=args[0].split("\\\\|");
Supplier<Stream<T>> st =null;
for(String argsSimple : argsArr)
//获取单个条件,拼接
String[] argsKV;
//不等
if(argsSimple.indexOf("!:")>0)
argsKV = argsSimple.split("!:");
st = () -> entry.getValue().stream()
.filter(x -> !(ReflectionUtil.getFiledValue(x, argsKV[0])==null?"null":ReflectionUtil.getFiledValue(x, argsKV[0]).toString()).equals(argsKV[1]));
else
//相等
argsKV = argsSimple.split(":");
st = () -> entry.getValue().stream()
.filter(x -> (ReflectionUtil.getFiledValue(x, argsKV[0])==null?"null":ReflectionUtil.getFiledValue(x, argsKV[0]).toString()).equals(argsKV[1]));
Object colVal = st.get()
.map(x -> new BigDecimal(ReflectionUtil.getFiledValue(x, args[1]) == null ? "0" : ReflectionUtil.getFiledValue(x, args[1]).toString().replace(",","")))
.reduce(BigDecimal.ZERO, BigDecimal::add);
obj.add(colVal);
else
Object colVal = entry.getValue().stream()
.map(x -> new BigDecimal(ReflectionUtil.getFiledValue(x, args[0]) == null ? "0" : ReflectionUtil.getFiledValue(x, args[0]).toString()))
.reduce(BigDecimal.ZERO, BigDecimal::add);
obj.add(colVal);
//计算列
else
Object colVal = entry.getValue().stream()
.map(x -> new BigDecimal(ReflectionUtil.getFiledValue(x, colName) == null ? "0" : ReflectionUtil.getFiledValue(x, colName).toString().replace(",","")))
.reduce(BigDecimal.ZERO, BigDecimal::add);
obj.add(colVal);
//添加到data
data.add(obj);
return data;
/**
* 添加合计列
*
* @param fieldNames 字段
* @param data 数据
* @param calculateHeadsNames 计算列
* @return
*/
public List<Object> addTotal(List<String> fieldNames, List<List<Object>> data, List<String> calculateHeadsNames)
List<Object> totalLine = new ArrayList<>();
try
//按照数据的长度,初始化大小
if (data.size() > 0)
data.get(0).forEach(x -> totalLine.add(""));
//增加TOTAL字样
totalLine.set(0, "TOTAL");
//计算列
if(calculateHeadsNames!=null && calculateHeadsNames.size()>0)
for (String colName : calculateHeadsNames)
Integer index = fieldNames.indexOf(colName);
if (index > -1)
BigDecimal val = data.stream().map(x -> new BigDecimal(x.get(index) == null ? "0" : x.get(index).toString()))
.reduce(BigDecimal::add).get();
totalLine.set(index, val);
return totalLine;
catch (Exception e)
e.printStackTrace();
finally
return totalLine;
三,测试
@Test
public void testLambda() throws NoSuchFieldException, IllegalAccessException
List<MyTest> list=new ArrayList<>();
list.add(new MyTest(0,"n0","hobby0",1));
list.add(new MyTest(1,"n1","hobby1",1));
list.add(new MyTest(1,"n2","hobby2",1));
list.add(new MyTest(2,"n3","hobby3",1));
list.add(new MyTest(2,"n4","hobby4",1));
list.add(new MyTest(3,"n5","hobby5",1));
list.add(new MyTest(3,"n6","hobby6",1));
list.add(new MyTest(3,"n7","hobby7",1));
list.add(new MyTest(3,"n8","hobby7",1));
String json = FileUtil.readFile(System.getProperty("user.dir") + "/reportArgs"+"/myTest.json");
ReportArgsReq reportArgsReq= JSON.parseObject(json,ReportArgsReq.class);
List<MyTest> rList = report.getDataListFilter(list, reportArgsReq.getEqualsMap(),reportArgsReq.getNotEqualsMap());
Map<String,List<MyTest>> rMap=report.getDataListGroup(rList,reportArgsReq.getFieldGroups());
System.out.println(rMap.size());
// List<FileTypeVO> rList=list.stream().filter(x->x.)
MyTest.java
package com.leadtrans.report.model.DB;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Date;
/**
* @author: Tyler
* @createDate: 2021/12/7
*/
@TableName(value = "myTest")
public class MyTest
@TableId
private Integer id;
private String name;
private String hobby;
private Integer amount;
public MyTest()
public MyTest(Integer id,String name,String hobby,Integer amount)
this.id=id;
this.name=name;
this.hobby=hobby;
this.amount=amount;
//get;set;
myTest.json
"equalsMap": ,
"notEqualsMap": ,
"fieldGroups": ["id"],
"headsExcel": ["id","name","hobby","amount sum"],
"fieldNames": ["id","name","hobby","sum(amount)"],
"calculateFieldNames": ["sum(amount)"]
四,进阶
其实还有一些其他的用法。
样例:
"equalsMap": "INCO": ["FOB","EXWORK"],"Test": ["a","b"],
"notEqualsMap": "Test1": ["hello"],"Test2": ["t1","t2"],
"fieldGroups": ["pol","pod","jobName"],
"headsExcel": ["jobName","pol","pod","INCO","TEU","AIR Bill","LCL Bill","jobProfit"],
"fieldNames": ["jobName","pol","pod","INCO","sum(type:SEA,TEU)","count(type:AIR,shipmentID)","count(mode:LCL,shipmentID)","jobProfit"],
"calculateFieldNames": ["sum(type:SEA|mode:FCL,TEU)","count(type:AIR,shipmentID)","count(mode:LCL,shipmentID)","jobProfit"],
"calcRatioHeads": ["TEU","AIR Bill","LCL Bill","jobProfit"],
"groupReportList": ["jobName","pol","pod"]
解释:
字段 | 注释 |
---|---|
equalsMap | 需要过滤的相等字段。 |
notEqualsMap | 需要过滤的不等字段。 |
fieldGroups | 分组字段。 |
headsExcel | 写入excel的表头 |
fieldNames | 使用到的字段,对应到表头。 |
calculateFieldNames | 需要计算的字段,int,decimal,非数值类型(Count)..... ( sum(type:SEA|mode:FCL,TEU) : 计算type为sea,并且mode为FCL 的TEU 总和 count(type:AIR,shipmentID):计算type为Air,的shipment数量 jobProfit / sum(jobProfit):同样的含义,直接计算jobProfit的总合 countDistinct(type:AIP,shipmentID):去重后计算count ) |
以上是关于java 动态 Lambda 的主要内容,如果未能解决你的问题,请参考以下文章
Android开发太难了:Java Lambda ≠ Android Lambda (上)
Android开发太难了:Java Lambda ≠ Android Lambda (上)