Lambda表达式
基本语法
Lambda表达式由3个部分组成:参数部分、->、逻辑部分。

整个Lambda表达式就是一个函数对象。
方法引用
基本语法


类型
类名::静态方法

类名::非静态方法

对象::非静态方法

类名::new

以上Student::new虽然长相一样,但是可以通过类型来区分。

this::非静态方法(3的特例,只能在类内部使用)
super::非静态方法(3的特例,只能在类内部使用)
函数接口
如果两个函数对象满足以下要求,那么就可以将他们归为一类,抽象为一个函数式接口。

在接口上方打上@FunctionalInterface注解以便在编译阶段检查接口是否满足条件有且仅有一个抽象方法。

常见函数接口

命名规则

!!!特例

闭包
形如(int y) -> x + y与它的外部变量形成了闭包。

!!!注意:变量x必须要是final或者effective final(虽然没有定义为final,但是后文并没有x进行过修改)。但是对象内部的值是可以修改的。


柯里化
让接受多个参数的函数转换成一系列只接受一个参数的函数的过程叫做柯里化。
例子如下:


Stream流
!!!特性
一次使用
两类操作(中间操作 lazy 懒惰,终结操作 eager 迫切)
一次使用
Stream<Integer> stream = Stream.of(1, 2, 3); stream.forEach(System.out::println); stream.forEach(System.out::println);
|
两类操作

过滤filter
Stream.of( new Student("jack", 18, "男"), new Student("marry", 20, "女"), new Student("tom", 15, "男") ).filter(stu -> stu.getAge() <= 18) .forEach(System.out::println);
}
|

映射map
Stream.of( new Student("jack", 18, "男"), new Student("marry", 20, "女"), new Student("tom", 15, "男") ).map(stu -> stu.getName() + "xixi") .forEach(System.out::println); }
|

降维(扁平化映射)flatMap
Stream.of( List.of(new Student("jack", 18, "男"), new Student("marry", 20, "女"), new Student("tom", 15, "男")), List.of(new Student("black", 18, "男"), new Student("sam", 20, "女"), new Student("sim", 15, "男")) ) .flatMap(list -> list.stream()) .forEach(System.out::println);
|

将外部的list的去除,得到list里面的数据。
构建流
用已有数据构建出Stream对象。
方式有以下三种:

集合构建流
List.of(1,2,3).stream(); Map.of("a",1,"b",2).entrySet().stream();
|
数组构建流
int[] array = new int[]{1,2,3}; Arrays.stream(array);
|
对象构建流
Stream.of( List.of(new Student("jack", 18, "男"), new Student("marry", 20, "女"), new Student("tom", 15, "男")), List.of(new Student("black", 18, "男"), new Student("sam", 20, "女"), new Student("sim", 15, "男")) )
|
流的合并concat
Stream<Integer> stream1 = Stream.of(1, 2, 3); Stream<Integer> stream2 = Stream.of(4, 5, 6);
Stream<Integer> concat = Stream.concat(stream1, stream2); concat.forEach(System.out::println);
|
截取
skip(long n) 跳过n个,保留剩余部分。
concat.skip(2).forEach(System.out::print);
|
limit(long n) 保留前n个数据,剩余的舍弃。
concat.limit(2).forEach(System.out::print);
|
takeWhile(Predicate p) 条件成立保留,一旦条件不成立,剩下的不要。
concat.takeWhile(x -> x < 3).forEach(System.out::print);
|
dropWhile(Predicate p) 条件成立舍弃,一旦条件不成立,剩下的保留。
concat.dropWhile(x->x >= 3).forEach(System.out::print);
|
生成流
不用现有数据生成Stream对象。
方式有以下三种:

IntStream.range(start,end)
IntStream.range(1,10).forEach(System.out::print); IntStream.rangeClosed(1,10).forEach(System.out::print);
|
IntStream.iterate(初始值,生成式) 或者IntStream.iterate(初始值,判断条件,生成式)
IntStream.iterate(1, x -> x + 2).limit(5).forEach(System.out::print); IntStream.iterate(1, x -> x <= 9 ,x -> x + 2).forEach(System.out::print);
|
IntStream.generate()
IntStream.generate(() -> ThreadLocalRandom.current().nextInt(100)).limit(5).forEach(System.out::println);
ThreadLocalRandom.current().ints(5,0,100).forEach(System.out::println);
|
查找
findFirst() 找到第一个
System.out.println(Stream.of(1, 2, 3, 4, 5, 6) .filter(x -> (x & 1) == 0) .findFirst() .orElse(-1));
Stream.of(1, 2, 3, 4, 5, 6) .filter(x -> (x & 1) == 0) .findFirst() .ifPresent(System.out::println);
|
findAny() 找到任意一个
Stream.of(1, 2, 3, 4, 5, 6) .filter(x -> (x & 1) == 0) .findAny() .ifPresent(System.out::println);
|
判断
anyMatch() 只要有任意一个符合,则返回true
System.out.println(Stream.of(1, 2, 3, 4, 5, 6) .anyMatch(x -> (x & 1) == 0));
|
allMatch() 全部符合才返回true
System.out.println(Stream.of(1, 2, 3, 4, 5, 6) .allMatch(x -> (x & 1) == 0));
|
noneMatch() 都不符合才返回true
System.out.println(Stream.of(1, 2, 3, 4, 5, 6) .noneMatch(x -> (x & 1) == 0));
|
去重
distinct()
Stream.of(1,2,3,4,1,2,4,5,7,6,8) .distinct() .forEach(System.out::print);
|
排序
sorted()
Stream.of(3,5,6,1,2,5,7,9,3,2) .sorted((a,b) -> a < b ? -1 : a == b ? 0 : 1) .forEach(System.out::print);
Stream.of(3,5,6,1,2,5,7,9,3,2) .sorted(Comparator.comparingInt(a -> a)) .forEach(System.out::print);
Stream.of(3,5,6,1,2,5,7,9,3,2) .sorted(Comparator.comparingInt(a -> (int) a).reversed()) .forEach(System.out::print);
|

以strength降序排序,在strength相同时以名字升序排序。
化简 reduce
两两合并
.reduce((p,x)->r)、.reduce(init,(p,x)->r) 其中p为上次的合并结果,x为当前元素,r为本次合并结果,init为初始值。
System.out.println(Stream.of( new Hero("张三", 90), new Hero("李四", 100), new Hero("王五", 89), new Hero("刘子", 78), new Hero("八爷", 69) ).reduce((h1, h2) -> h1.strength > h2.strength ? h1 : h2));
System.out.println(Stream.of( new Hero("张三", 90), new Hero("李四", 100), new Hero("王五", 89), new Hero("刘子", 78), new Hero("八爷", 69) ).reduce(new Hero("-",-1),(h1, h2) -> h1.strength > h2.strength ? h1 : h2));
|
底层为reduce的一些方法,求最值、平均数、数量等。
System.out.println(Stream.of( new Hero("张三", 90), new Hero("李四", 100), new Hero("王五", 89), new Hero("刘子", 78), new Hero("八爷", 69) ).count());
System.out.println(Stream.of( new Hero("张三", 90), new Hero("李四", 100), new Hero("王五", 89), new Hero("刘子", 78), new Hero("八爷", 69) ).max(Comparator.comparingInt(Hero::strength)));
|
收集器
Stream.of("张胜男","李四","王五","刘子","八爷") .collect(Collectors.toList()) .forEach(System.out::println);
Stream.of("张胜男","李四","王五","刘子","八爷") .collect(Collectors.toSet()) .forEach(System.out::println);
Stream.of("张胜男", "李四", "王五", "刘子", "八爷") .collect(Collectors.toMap(name -> name, name -> 1)) .forEach((key,value) -> System.out.println(key + ":" + value));
|
实际应用中Collectors.toMap基本很少用,常用的是Collectors.groupingBy()来做分组需求
Stream.of("张胜男", "李四", "王五", "刘子", "八爷") .collect(Collectors.groupingBy(String::length,Collectors.toList())) .forEach((key,value) -> System.out.println(key+":"+value));
|

下游收集器(配合Collectors.groupingBy()使用)
Stream.of( new Hero("张胜男", 90), new Hero("李四", 100), new Hero("王五", 89), new Hero("刘子", 78), new Hero("八爷", 69) ).collect(Collectors.groupingBy(h -> h.name.length(), Collectors.mapping(h -> h.strength, Collectors.toList()))) .forEach((key, value) -> System.out.println(key + " : " + value));
|
Stream.of( new Hero("张胜男", 90), new Hero("李四", 100), new Hero("王五", 89), new Hero("刘子", 78), new Hero("八爷", 69) ).collect(Collectors.groupingBy(h -> h.name.length(), Collectors.flatMapping(h -> h.name.chars().mapToObj(Character::toString),Collectors.toList()))) .forEach((key, value) -> System.out.println(key + " : " + value));
|
结果如下:
Stream.of( new Hero("张胜男", 90), new Hero("李四", 100), new Hero("王五", 89), new Hero("刘子", 78), new Hero("八爷", 69) ).collect(Collectors.groupingBy(h -> h.name.length(), Collectors.counting())) .forEach((key, value) -> System.out.println(key + " : " + value));
|
Stream.of( new Hero("张胜男", 90), new Hero("李四", 100), new Hero("王五", 89), new Hero("刘子", 78), new Hero("八爷", 69) ).collect(Collectors.groupingBy(h -> h.name.length(), Collectors.mapping(h -> h.strength,Collectors.reducing(0,(p,x) -> p + x)))) .forEach((key, value) -> System.out.println(key + " : " + value));
|


基本流
IntStream 、LongStream 、DoubleStream 。