Lambda表达式
注意和Python中Lambda的区别,在Python中是方法,在Java中是对象。
无参,无返回值
@Test
public void test() {
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("1");
}
};
r1.run();
System.out.println("*************");
Runnable r2 = () -> System.out.println("2");
r2.run();
}
结果:
1
*************
2
有一个参数,无返回值
@Test
public void test2() {
Consumer<String> c1 = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
c1.accept("1");
System.out.println("************");
Consumer<String> c2 = (String s) -> {
System.out.println(s);
};
c2.accept("2");
}
结果:
1
************
2
数据类型可以省略 类型推断
在上面代码的基础上:
@Test
public void test2() {
Consumer<String> c1 = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
c1.accept("1");
System.out.println("************");
Consumer<String> c2 = (String s) -> {
System.out.println(s);
};
c2.accept("2");
System.out.println("********");
Consumer<String> c3 = (s) -> {
System.out.println(s);
};
c3.accept("3");
}
结果:
1
************
2
********
3
下图也是类型推断:
若只有一个参数,参数的小括号可以省略
@Test
public void test3() {
Consumer<String> c3 = (s) -> {
System.out.println(s);
};
c3.accept("1");
System.out.println("*********");
Consumer<String> c4 = s -> {
System.out.println(s);
};
c4.accept("2");
}
结果:
1
*********
2
两个参数,且方法体中可能有多条语句和返回值
@Test
public void test4() {
Comparator<Integer> c1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
System.out.println(c1.compare(15, 20));
System.out.println("***********");
Comparator<Integer> c2 = (o1, o2) -> {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
System.out.println(c1.compare(25, 20));
}
结果:
15
20
-1
***********
25
20
1
当Lambda体只有一条语句时,return与大括号若有,都可以省略
@Test
public void test5() {
Comparator<Integer> c1 = (o1, o2) -> {
return o1.compareTo(o2);
};
System.out.println(c1.compare(25, 20));
System.out.println("***********");
Comparator<Integer> c2 = (o1, o2) -> o1.compareTo(o2);
System.out.println(c2.compare(20, 25));
}
结果:
1
***********
-1
Lambda 总结
函数式接口
如果一个接口中只声明了一个抽象方法,则此接口称为函数式接口。
Lambda表达式只能用于接口中有一个抽象方法的情况,因此再实现抽象方法时就不必再指定方法名了,反正就那一个。也就是说Lambda表达式作为函数式接口的实例。
Consumer
@Test
public void test6() {
shopping(1000, new Consumer<Double>() {
@Override
public void accept(Double aDouble) {
System.out.println("购物共花费: " + aDouble);
}
});
shopping(1500, money -> System.out.println("购物共花费: " + money) );
}
public void shopping(double money, Consumer<Double> con) {
con.accept(money);
}
结果:
购物共花费: 1000.0
购物共花费: 1500.0
Predicate
其他接口
方法引用
使用举例
对象::非静态方法
类::静态方法
类::非静态方法
@Test
public void test7() {
Function<Person, String> f = new Function<Person, String>() {
@Override
public String apply(Person person) {
return person.getName();
}
};
System.out.println(f.apply(new Person("Li")));
System.out.println("******");
Function<Person, String> f2 = p -> p.getName();
System.out.println(f2.apply(new Person("Wang")));
System.out.println("******");
Function<Person, String> f3 =Person :: getName;
System.out.println(f3.apply(new Person("Zhao")));
}
Li
******
Wang
******
Zhao
构造器引用
数组引用
Stream API
Stream是延迟执行的,只有在需要结果的时候才会执行
创建Stream对象的方式
通过集合
通过数组
通过Stream的of()
无限流
中间操作
筛选与切片
再次注意,一旦对Stream执行了中止操作(forEach输出也算中止操作),后续的操作就无法执行了,因此下图会报错:
因此要重新生成一个stream,就像iterator那样:
映射
Map
@Test
public void test() {
List<String> list = Arrays.asList("AA", "Bb", "aBc");
list.stream().map(s -> s.toUpperCase()).forEach(System.out::println);
System.out.println(list);
}
AA
BB
ABC
[AA, Bb, aBc]
flatmap
接收一个函数作为参数,将流中的每一个值换成另一个流,然后把所有流连接成一个流。
https://www.bilibili.com/video/BV1Kb411W75N?p=680
排序
sorted()
要想使用这个方法,相应的类需实现Comparable接口,排序后原集合不变。
调用sorted方法后会自动调用Integer的排序方法:
@Test
public void test() {
List<Integer> list = Arrays.asList(18, 22, -1, 34, 14, 0);
list.stream().sorted().forEach(x -> System.out.println(x));
System.out.println(list); // 验证排序后原list是否改变
}
结果:
-1
0
14
18
22
34
[18, 22, -1, 34, 14, 0]
但要注意,如果我们想对对象列表进行排序,则相应的类要实现Comparable接口,或者使用另一种sorted()
sorted(Comparator com)
可以在sorted传入Comparator 实现类的对象以实现定制排序:
@Test
public void test() {
List<Integer> list = Arrays.asList(18, 22, -1, 34, 14, 0);
list.stream().sorted(new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
return - o1.compareTo(o2);
}
}).forEach(System.out::println);
}
结果:
34
22
18
14
0
-1
中止操作
匹配和查找
public class StopTest {
@Test
public void test1() {
List<Integer> list = Arrays.asList(10, 5, -1, 32, 44, -11, 57);
// allMatch 看看stream里面的元素是否都满足参数的条件
boolean res = list.stream().allMatch(l -> l > -20); // true
System.out.println(res);
// anyMatch stream里有一个满足参数的条件就行
boolean res2 = list.stream().anyMatch(l -> l > 50); // true
System.out.println(res2);
// noneMatch 检查是否没有匹配的元素,若有则返回false
boolean res3 = list.stream().noneMatch(e -> e.equals(5)); // false
System.out.println(res3);
// findfirst 返回第一个元素,注意返回值类型是Optional,后面会说
Optional<Integer> res4 = list.stream().sorted().findFirst(); // Optional[-11]
System.out.println(res4);
// findAny 返回当前流中任意一个元素
Optional<Integer> res5 = list.stream().findAny(); // Optional[10]
System.out.println(res5);
// count 返回流中元素的总个数
long count = list.stream().count(); // 7
System.out.println(count);
// max 返回流中的最大值
// Optional<Integer> max_num = list.stream().max(new Comparator<Integer>() {
// @Override
// public int compare(Integer o1, Integer o2) {
// return o1.compareTo(o2);
// }
// });
Optional<Integer> max_num = list.stream().map(l -> l*l).max((o1, o2) -> o1.compareTo(o2)); // Optional[3249]
System.out.println(max_num);
// min 返回流中的最小值,min的参数可以对流进行处理(升序/降序/...)
Optional<Integer> min_num = list.stream().min((l1, l2) -> l1.compareTo(l2)); // Optional[-11]
System.out.println(min_num);
// forEach 流的迭代
list.stream().forEach(l -> System.out.println(l));
System.out.println("***"); // 10 5 -1 32 44 -11 57
// 集合的迭代
list.forEach(l -> System.out.println(l)); // 10 5 -1 32 44 -11 57
}
}
归约
// 归约
@Test
public void test2() {
// T reduce(T identity, BinaryOperator<T> accumulator) 第一个参数是初始值,会附加到最后的结果上,第二个参数是对集合中元素的操作,在这里是相加
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = list.stream().reduce(5, (l1, l2) -> Integer.sum(l1, l2)); // 60
System.out.println(sum);
// Optional<T> reduce(BinaryOperator<T> accumulator)
Optional<Integer> sum2 = list.stream().reduce((l1, l2) -> Integer.sum(l1, l2)); // Optional[55]
System.out.println(sum2);
}
收集
// 收集
@Test
public void test3() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> collect = list.stream().filter(l -> l > 5).collect(Collectors.toList());
collect.forEach(l -> System.out.println(l));
}
结果:
6
7
8
9
10
Optional类
https://www.bilibili.com/video/BV1Kb411W75N?p=687
其它
还有些新版本的特性,俺是个新手,现在也用不到,等以后再来填坑吧! ()