Lambda表达式使用记录
Lambda表达式,即函数式编程,可以将行为进行传递。
大致意思:使用不可变值与函数,函数对不可变值进行处理,映射成另一个值。
1 lambda遍历
先创建一个测试类,遍历时候用
package com.peiyj.entity;
import lombok.Data;
import lombok.ToString;
import java.util.Date;
@Data
@ToString
public class LambdaTest {
private Long id;
private Integer age;
private String name;
private Date time;
public LambdaTest() {
}
public LambdaTest(Long id, Integer age, String name, Date time) {
this.id = id;
this.age = age;
this.name = name;
this.time = time;
}
遍历数组、List、Map集合
@Test
public void traverse() {
//遍历数组
Integer[] items = {1, 2, 3};
//先转化为List再遍历
Arrays.asList(items).forEach(System.out::println);
//遍历List集合
List list = Lists.newArrayList();
list.add(new LambdaTest(1L,20,"xiaoming",new Date()));
list.add(new LambdaTest(4L,25,"xiaoxiao",new Date()));
list.forEach(System.err::println);
//遍历Map集合
Map<String, Integer> map = Maps.newHashMap();
map.put("1", 7);
map.put("2", 8);
map.put("3", 9);
map.forEach((key, value) -> {
System.out.println("key: "+key + " value: " + value);
});
}
打印结果
1
2
3
LambdaTest(id=1, age=20, name=xiaoming, time=Sun Feb 07 16:44:41 CST 2021)
LambdaTest(id=4, age=25, name=xiaoxiao, time=Sun Feb 07 16:44:41 CST 2021)
key: 1 value: 7
key: 2 value: 8
key: 3 value: 9
2 Predicate函数-断定式子
其实就是判断真假 判断参数符不符合规则
Predicate的方法有:
test():判断
and():添加且的规则
or():添加或的规则
negate():取反
还有一个静态方法:
isEqual()
@Test
public void predicate(){
//说白就是先定义一个规则 然后判断传入的值是否满足这个规则
//定义规则
Predicate<Integer> predicate = x -> x > 30;
//test() 验证参数是否符合规则 返回值boolean
boolean test = predicate.test(25);
System.out.println(test);//false
//或者
System.out.println(
predicate.test(
new LambdaTest(1L,35,"xiaoming",new Date())
.getAge()
)
);//true
//或者
Predicate<String> predicate2 = x -> x == "xiaoming" || x == "xiaoxiao";
System.out.println(predicate2.test("abc"));//false
//and() 就是再添加一个规则
predicate.and(x -> x < 60);
System.out.println(predicate.test(35));//true
//or() 或者符合另一个规则
predicate.or(x -> x == 100);
System.out.println(predicate.test(100));//true
//negate() 取反
System.out.println(predicate.negate().test(100));//false
//isEqual() 静态方法
Predicate<Object> p = Predicate.isEqual("xiaohong");
boolean x = p.test("xiaohong");
System.out.println(x);//true
}
3 Consumer-消费信息
@Test
public void consumer(){
Consumer<Object> consumer = System.out::println;
consumer.accept("这和System....打印有什么区别..");
consumer.accept("然而...");
List list = Lists.newArrayList();
list.add("1");
list.add("2");
consumer.accept(list);
Map map = Maps.newHashMap();
map.put("1",1);
map.put("2",2);
map.put("3",3);
consumer.accept(map);
LambdaTest lambdaTest = new LambdaTest();
lambdaTest.setId(10L);
lambdaTest.setAge(20);
lambdaTest.setName("30");
lambdaTest.setTime(new Date());
consumer.accept(lambdaTest);
consumer.accept("注:对象没有ToString也能打印");
}
控制台输出:
这和System....打印有什么区别..
然而...
[1, 2]
{1=1, 2=2, 3=3}
LambdaTest(id=10, age=20, name=30, time=Mon Feb 08 14:51:44 CST 2021)
注:对象没有ToString也能打印
4 Function-将T映射为R(转换功能)
Funtion接口,定义了一个apply的抽象类,接收一个泛型T对象,并且返回泛型R对象
//静态方法
Function.identity();
//传入的参数类型为T返回类型为R
function.apply();
//1先运行apply() 2再运行andThen()
function.andThen();
//1先运行compose() 2再运行apply()
function.compose();
function.apply();
@Test
public void function(){
LambdaTest lambdaTest = new LambdaTest();
lambdaTest.setName("xiaoxiao");
Function<LambdaTest,String> function = LambdaTest::getName;
String name = function.apply(lambdaTest);
System.out.println(name);
}
Function.identity()
@Test
public void function(){
List<LambdaTest> lambdaTests = new ArrayList<>();
lambdaTests.add( new LambdaTest(1L, 20, "x", new Date()));
lambdaTests.add( new LambdaTest(2L, 25, "y", new Date()));
lambdaTests.add( new LambdaTest(3L, 30, "xiaoming", new Date()));
lambdaTests.add( new LambdaTest(4L, 40, "xiaoxiao", new Date()));
Map<String, LambdaTest> map =
lambdaTests.stream()
.collect(Collectors.toMap(LambdaTest::getName, Function.identity()));
map.forEach((k,v) ->{
System.err.println(k + "-----------" + v);
});
Map<String, LambdaTest> collect = lambdaTests.stream()
.filter(x -> x.getName() != "x")
.collect(Collectors.toMap(LambdaTest::getName, Function.identity()));
collect.forEach((k,v) ->{
System.out.println(k + "-----------" + v);
});
}
输出:
xiaoming-----------LambdaTest(id=3, age=30, name=xiaoming, time=Tue Feb 09 16:02:10 CST 2021)
x-----------LambdaTest(id=1, age=20, name=x, time=Tue Feb 09 16:02:10 CST 2021)
y-----------LambdaTest(id=2, age=25, name=y, time=Tue Feb 09 16:02:10 CST 2021)
xiaoxiao-----------LambdaTest(id=4, age=40, name=xiaoxiao, time=Tue Feb 09 16:02:10 CST 2021)
xiaoming-----------LambdaTest(id=3, age=30, name=xiaoming, time=Tue Feb 09 16:02:10 CST 2021)
y-----------LambdaTest(id=2, age=25, name=y, time=Tue Feb 09 16:02:10 CST 2021)
xiaoxiao-----------LambdaTest(id=4, age=40, name=xiaoxiao, time=Tue Feb 09 16:02:10 CST 2021)
@Test
public void function(){
Function<Integer,Integer> function = x -> x * 2;
Function<Integer,Integer> function1 = x -> x * x;
//3*2 * (3*2)
System.out.println(function.andThen(function1).apply(3));//36
//3*3 * 2
System.err.println(function.compose(function1).apply(3));//18
}
function.andThen();
function.compose();
@Test
public void function(){
Function<Integer,Integer> function = x -> x * 2;
Function<Integer,Integer> function1 = x -> x * x;
//3*2 * (3*2)
System.out.println(function.andThen(function1).apply(3));//36
//3*3 * 2
System.err.println(function.compose(function1).apply(3));//18
}
4 Supplier-生产者
get():生产数据
@Test
public void supplier(){
//创建Supplier容器,声明类型,此时不会调用对象的构造方法
Supplier<LambdaTest> lambdaTestSupplier = LambdaTest::new;
//get()方法,调用对象的构造方法,获取对象
//每次get()都会创建新的对象
if(lambdaTestSupplier.get() == lambdaTestSupplier.get()){
System.out.println("对象的地址相同");
}else {
System.out.println("对象的地址不同");
}
}
输出:
对象的地址不同
获取当前日期
//生产者 获取当前日期
@Test
public void supplier2(){
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.err.println(dtf.format(LocalDateTime.now()));
Supplier<String> s = () -> dtf.format(LocalDateTime.now());
System.out.println(s.get());
}
5 UnaryOperator-生成同类型对象-一元操作
UnaryOperator继承Function接口,对数据进行操作,生成一个与同类型对象
@Test
public void unaryOperator(){
UnaryOperator<Boolean> unaryOperator = uglily -> !uglily;
Boolean apply = unaryOperator.apply(true);
System.out.println(apply);
//用函数接口的返回结果替代原list中的值
List<Integer> list = Lists.newArrayList();
list.add(1);
list.add(2);
list.add(3);
list.forEach(System.out::println);
list.replaceAll(x -> x + 10);
list.forEach(System.err::println);
}
6 BinaryOperator-二元操作
静态方法:
minBy: 获取最小值
maxBy:获取最大值
//二元操作
@Test
public void binaryOperator(){
BinaryOperator<Integer> operator = (x, y) -> x * y;
Integer i = operator.apply(2, 3);
System.out.println(i);
//BinaryOperator中有两个静态方法 比较大小
//minBy 获取最小值
//maxBy 获取最大值
//比较两个数字大小
BinaryOperator<Integer> binaryOperatorMin =
BinaryOperator.minBy(Comparator.naturalOrder());
System.out.println(binaryOperatorMin.apply(2, 5));
//比较两个数字大小
BinaryOperator<Integer> binaryOperatorMax =
BinaryOperator.maxBy(Comparator.naturalOrder());
System.out.println(binaryOperatorMax.apply(2, 5));
//比较两个Double大小
BinaryOperator<Double> binaryOperatorMinDouble =
BinaryOperator.minBy(Comparator.naturalOrder());
Double apply = binaryOperatorMinDouble.apply(10.1, 11.0);
System.out.println(apply);
//比较字符串大小
BinaryOperator<String> binaryOperatorMaxString =
BinaryOperator.maxBy(Comparator.naturalOrder());
String apply1 = binaryOperatorMaxString.apply("a", "b");
System.out.println(apply1);
}
7 stream
Java 8新增的接口,表示数据流
大概意思: 创建一个流,或者把一系列数据转化为流,
转化为流之后,可以对流进行操作,可以把流再转化为一系列的数据
1 流的创建
Stream中的静态方法:
of() 创建有限流
iterate() 创建无限流
generate() 创建无限流 (需要依次生成一系列值的时候使用iterate较多)
@Test
public void streamStatic(){
Stream<Integer> stream = Stream.of(7,8,11,1,2,3,4,5,6);
stream.forEach(System.out::println);
Stream<Integer> stream2 =
Stream.iterate(0, (x) -> x + 1).limit(10);
stream2.forEach(System.out::println);
Stream<Double> stream3 =
Stream.generate(Math::random).limit(2);
stream3.forEach(System.err::println);
}
@Test
public void test(){
//stream:支持并行流与顺序流
//并行流:多个线程同时运行
//顺序流:使用主线程,单线程
List<String> list = Lists.newArrayList();
//获取一个顺序流
Stream<String> stream = list.stream();
//获取一个并行流
Stream<String> parallelStream = list.parallelStream();
}
2 流的中间操作
(1)流的中间操作-筛选与切片
//流的中间操作-筛选与切片
@Test
public void streamMiddle(){
//filter:过滤流中的某些元素
//distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素
//skip(n):跳过n元素,配合limit(n)可实现分页
//limit(n):获取n个元素
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Stream<Integer> limit =
list.stream()
.filter(x -> x > 5)
.distinct()
.skip(0)
.limit(10);
limit.forEach(System.out::println);
}
(2)流的中间操作-映射
//流的中间操作-映射
@Test
public void streamMapping(){
//map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
//flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
List<String> list = Arrays.asList("1,2,3","a,b,c");
Stream<String> stringStream = list.stream()
.map(x -> x.replaceAll(",", ""));
stringStream.forEach(System.out::println);
Stream<String> stringStream1 = list.stream()
.flatMap(x -> {
String[] split = x.split(",");
Stream<String> s = Stream.of(split);
return s;
});
stringStream1.forEach(System.out::println);
}
(3)流的中间操作-排序
//流的中间操作-排序
@Test
public void streamSorting(){
//sorted():自然排序,流中元素需实现Comparable接口
//sorted(Comparator com):定制排序,自定义Comparator排序器
List<String> list = Arrays.asList("aa","zz","dd");
list.stream()
.sorted()
.forEach(System.out::println);
LambdaTest t1 = new LambdaTest(1L, 60, "a", new Date());
LambdaTest t2 = new LambdaTest(2L, 20, "h", new Date());
LambdaTest t3 = new LambdaTest(3L, 30, "x", new Date());
LambdaTest t4 = new LambdaTest(4L, 40, "y", new Date());
LambdaTest t5 = new LambdaTest(5L, 50, "a", new Date());
LambdaTest t6 = new LambdaTest(6L, 70, "a", new Date());
List<LambdaTest> lambdaTests = Arrays.asList(t1, t2, t3, t4, t5,t6);
lambdaTests.stream().sorted(
(x, y) -> {
if (x.getName().equals(y.getName())) {
System.out.println(x.getAge() - y.getAge());
// return x.getAge() - y.getAge();//升序
return y.getAge() - x.getAge();//降序
} else {
// return x.getName().compareTo(y.getName());//升序
return y.getName().compareTo(x.getName());//降序
}
}
).forEach(System.out::println);
}
(4)流的中间操作-消费
//流的中间操作-消费
@Test
public void streamPeek(){
//peek:如同于map,能得到流中的每一个元素。
//但map接收的是一个Function表达式,有返回值;
//而peek接收的是Consumer表达式,没有返回值。
//peek用来修改数据,map用来转换数据类型。
LambdaTest t1 = new LambdaTest(1L, 60, "a", new Date());
LambdaTest t2 = new LambdaTest(2L, 20, "h", new Date());
LambdaTest t3 = new LambdaTest(3L, 30, "x", new Date());
LambdaTest t4 = new LambdaTest(4L, 40, "y", new Date());
LambdaTest t5 = new LambdaTest(5L, 50, "a", new Date());
LambdaTest t6 = new LambdaTest(6L, 70, "a", new Date());
List<LambdaTest> lambdaTests = Arrays.asList(t1, t2, t3, t4, t5,t6);
lambdaTests.stream()
.peek(x -> x.setAge(100))
.forEach(System.out::println);
}
3 流的终止操作
匹配 聚合操作
//流的终止操作-匹配 聚合
@Test
public void streamAggregation(){
//allMatch: 接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false
//noneMatch: 接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false
//anyMatch: 接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false
//findFirst: 返回流中第一个元素
//findAny: 返回流中的任意元素
//count: 返回流中元素的总个数
//max: 返回流中元素最大值
//min: 返回流中元素最小值
LambdaTest t1 = new LambdaTest(1L, 60, "a", new Date());
LambdaTest t2 = new LambdaTest(2L, 20, "h", new Date());
LambdaTest t3 = new LambdaTest(3L, 30, "x", new Date());
LambdaTest t4 = new LambdaTest(4L, 40, "y", new Date());
LambdaTest t5 = new LambdaTest(5L, 50, "a", new Date());
LambdaTest t6 = new LambdaTest(6L, 70, "a", new Date());
List<LambdaTest> lambdaTests = Arrays.asList(t1, t2, t3, t4, t5,t6);
//allMatch: 接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false
System.out.println(lambdaTests.stream().allMatch(x -> x.getAge() > 30));
//noneMatch: 接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false
System.out.println(lambdaTests.stream().noneMatch(x -> x.getAge() < 10));
//anyMatch: 接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false
System.out.println(lambdaTests.stream().anyMatch(x -> x.getAge() > 60));
//findFirst: 返回流中第一个元素
//findFirst返回的是Optional
Optional<LambdaTest> first = lambdaTests.stream().findFirst();
LambdaTest lambdaTest = first.get();
System.out.println(lambdaTest);
System.out.println(lambdaTests.stream().findFirst().get().getAge());
//findAny: 返回流中的任意元素
//串行情况下,一般返回第一个元素
System.out.println(lambdaTests.stream().findAny().get());
//并行情况下,不能确保是第一个
System.out.println(lambdaTests.parallelStream().findAny().get());
//count: 返回流中元素的总个数
System.out.println(lambdaTests.stream().count());
//max: 返回流中元素最大值
//考虑到方便,创建一个Integer的List
List<Integer> integers = lambdaTests.stream()
.map(x -> x.getAge())
.collect(Collectors.toList());
System.out.println(integers.stream().max(Integer::compareTo).get());
//min: 返回流中元素最小值
System.out.println(integers.stream().min(Integer::compareTo).get());
}
findAny演示
//findAny
@Test
public void findAny(){
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
for(int i=0;i<100;i++){
Integer integer = list.stream().findAny().get(); //获取一个顺序流
Integer any = list.parallelStream().findAny().get(); //获取一个并行流
if(any == 1){
System.out.println("1--" + i);
}else if(any == 2){
System.err.println("2--" + i);
}else if(any == 3){
System.out.println("3--" + i);
}else if(any == 4){
System.err.println("4--" + i);
}else if(any == 5){
System.out.println("5--" + i);
}
}
}
8 stream合并List
flatMap(),合并list
@Test
public void stream(){
List<LambdaTest> list = Lists.newArrayList();
list.add(new LambdaTest(1L, 20, null, null));
list.add(new LambdaTest(2L, 30, null, null));
list.add(new LambdaTest(3L, 40, null, null));
List<LambdaTest> list1 = Lists.newArrayList();
list1.add(new LambdaTest(1L, null, "xiaoming", new Date()));
list1.add(new LambdaTest(2L, null, "xiaohong", new Date()));
list1.add(new LambdaTest(3L, null, "xiaoqiang", new Date()));
List<LambdaTest> collect = list.stream()
.flatMap(x -> list1.stream()
.filter(y -> x.getId() == y.getId())
.map(y -> new LambdaTest(y.getId(), x.getAge(),y.getName(), y.getTime())))
.collect(Collectors.toList());
collect.forEach(System.out::println);
}