前言
Lambda表达式是 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数,也即是可以将函数作为参数传递到方法中。使用 Lambda 表达式可以使我们的代码变的更加简洁紧凑也更便于我们理解。
该文章仅仅只是记录一下本人在工作中用到的一些示例,不会介绍Lambda的一些底层原理,如函数式接口、方法引用等。如果大家需要了解这些知识,还请各位自行查阅相关资料。
准备工作
为了便于后续示例的编写,需要首先定义一个实体类:
package com.learn.lambda;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class LambdaDemo {
private String item;
private Integer statNum;
private String itemValue;
/**
* 扩展字段 写入任意信息
*/
private Object extendInfo;
public LambdaDemo(String item, Integer statNum) {
this.item = item;
this.statNum = statNum;
}
}
初始化样例数据:
private static List<LambdaDemo> demoList = new ArrayList<>();
static {
LambdaDemo demo1 = new LambdaDemo("001",100);
LambdaDemo demo2 = new LambdaDemo("002",200);
LambdaDemo demo3 = new LambdaDemo("003",300);
LambdaDemo demo4 = new LambdaDemo("004",400);
LambdaDemo demo5 = new LambdaDemo("005",500);
LambdaDemo demo6 = new LambdaDemo("006",600);
LambdaDemo demo7 = new LambdaDemo("007",700);
LambdaDemo demo8 = new LambdaDemo("008",800);
LambdaDemo demo9 = new LambdaDemo("009",900);
LambdaDemo demo10 = new LambdaDemo("010",1000);
demoList.add(demo1);
demoList.add(demo2);
demoList.add(demo3);
demoList.add(demo4);
demoList.add(demo5);
demoList.add(demo6);
demoList.add(demo7);
demoList.add(demo8);
demoList.add(demo9);
demoList.add(demo10);
}
到此准备工作基本已经完成。
示例
List集合转为Map集合
转换成map是如果没有重复key的情况是可以使用下边的方式
/**
* list转为Map
*/
public static void listToMap(){
Map<String, Integer> collect = demoList.stream().collect(Collectors.toMap(LambdaDemo::getItem, LambdaDemo::getStatNum));
collect.forEach((key,value)-> System.out.println(key+":"+value));
//如果value 为空的话 可以进行下判断
Map<String, Integer> map = demoList.stream().collect(Collectors.toMap(LambdaDemo::getItem, p -> p.getStatNum() == null ? 0 : p.getStatNum()));
System.out.println(map);
}
如果转换成map后有重复key值的话将会出现报错,将
样例数据
设置为有key值重复的情况。
LambdaDemo demo1 = new LambdaDemo("001",100);
LambdaDemo demo2 = new LambdaDemo("001",200);
再次执行上边的代码将会出现如下错误:
Exception in thread "main" java.lang.IllegalStateException: Duplicate key 100
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1254)
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
解决该问题其实也很简单,如下是将重复key的value值相加,如果是String类型的话可以使用逗号隔开进行拼接。具体根据自己的实际业务需求进行相应的处理。
/**
* list转为Map 解决重复key值的问题
* 将值相加
*/
public static void listToMapSolveDuplicateKey(){
Map<String, Integer> collect = demoList.stream().collect(Collectors.toMap(LambdaDemo::getItem, LambdaDemo::getStatNum,(oleValue,newValue)->oleValue+newValue));
collect.forEach((key,value)-> System.out.println(key+":"+value));
}
运行输出结果为:
001:300 //001的值为300,说明已经将重复key值的value相加
003:300
004:400
005:500
006:600
007:700
008:800
009:900
010:1000
还可以进行覆盖操作:
/**
* list转为Map 解决重复key值的问题
* 将值覆盖
*/
public static void listToMapSolveDuplicateKey2(){
Map<String, Integer> collect = demoList.stream().collect(Collectors.toMap(LambdaDemo::getItem, LambdaDemo::getStatNum,(oleValue,newValue)->newValue));
collect.forEach((key,value)-> System.out.println(key+":"+value));
}
关键点就在于使用哪一个值,oleValue为第一个key对应的值,newValue为第二个相同key对应的值。
(oleValue,newValue)->newValue)
(oleValue,newValue)->oleValue)
list转为Map集合并进行分组
Map<String, List<LambdaDemo>> stringListMap =regionList.stream().collect(Collectors.groupingBy(LambdaDemo::getItem));
计算对象中的某值之和
/**
* list 计算对象中的某值之和
*/
public static void listSum(){
int sum = demoList.stream().mapToInt(LambdaDemo::getStatNum).sum();
System.out.println(sum);
}
除了mapToInt方法外,还有mapToDouble、mapToLong等方法。可以按需使用。
list转换为字符串
逗号也可以根据需求换成其他相关的符号
/**
* 将list转换为使用逗号隔开的字符串
*/
public static void listToString(){
String value = demoList.stream().map(lambdaDemo -> String.valueOf(lambdaDemo.getItem())).collect(Collectors.joining(","));
System.out.println(value);
}
list转换为list
样例数据中的list中存放的是对象,我们可以将对对象中的item抽取出来转换成一个新的list
/**
* list转换为list
*/
public static void listToList(){
List<String> stringList = demoList.stream().map(LambdaDemo::getItem).collect(Collectors.toList());
stringList.forEach(System.out::println);
}
删除数据
使用Lambda删除数据也是非常方便的:
/**
* 删除数据
*/
public static void removeData(){
demoList.removeIf(lambdaDemo->lambdaDemo.getItem().equals("001"));
demoList.forEach(lambdaDemo -> System.out.println(lambdaDemo.getItem()));
}
排序
将样例数据中的statNum的数据打乱,可以使用如下方式进行排序:
/**
* 排序
*/
public static void sortData() {
//正序
demoList.sort(Comparator.comparing(LambdaDemo::getStatNum));
demoList.forEach(lambdaDemo -> System.out.println(lambdaDemo.getStatNum()));
System.out.println("----------");
//倒序
demoList.sort(Comparator.comparing(LambdaDemo::getStatNum).reversed());
demoList.forEach(lambdaDemo -> System.out.println(lambdaDemo.getStatNum()));
}
过滤
过滤也是比较常用的,比如我们过滤出statNum等于500的记录
/**
* 过滤
*/
public static void filter(){
Stream<LambdaDemo> lambdaDemoStream = demoList.stream().filter(lambdaDemo -> lambdaDemo.getStatNum() == 500);
lambdaDemoStream.forEach(lambdaDemo -> {
System.out.println(lambdaDemo.getStatNum());
});
}
以上只是本人在当前工作中使用到的部分示例,意在做下简单记录以备忘记时及时查询。我会不定时更新,欢迎大家评论区补充!