Stream流与lambda都是JDK8提供的特性
1 Stream流
流用来操作集合与数组数据
1.1 获取Stream流
(1) list:list.stream();
(2) map:map.keySet().stream()
map.keySet().stream();
map.values().stream();
map.entrySet().stream();
(3) 数组:Arrays.stream(...);
Arrays.stream(数组);
Stream.of(数组);
1.2 处理Stream
(1) 过滤:stream.filter(o -> o.equals("xx")) // 保留满足条件的对象,(类似SQL的where过滤)
(2) 排序:stream.sorted(Comparator); // Comparator参数对对象排序
(3) 掐头:stream.skip(long); // 跳过指定个数的前几个元素,获取后面元素
(4) 去尾:stream.limit(long); // 获取指定个数的前几个元素
(5) 去重:stream.distinct(); // 去掉重复元素
(6) 加工:stream.map(o -> o = o + "abc" ); // 修改元素或对象的属性值
(7) 合并:Stream.concat(stream1, stream2);
1.3 终止处理
终止方法处理后不再返回Stream流,流不能重复使用,每次使用需要重新获取。
(1) 总计: long count = stream.count();
(2) 最大: Object obj = stream.max(Comparator); // 返回最大对象
(3) 最小: Object obj = stream.min(Comparator); // 返回最小对象
(4) 列表: List list = stream.collect(Collectors.toList());
List list = stream.toList();
Set<String> set = stream.collect(Collectors.toSet());
Map map = stream.collect(Collectors.toMap(o->o.getName(), o->o.getAge()));
String\[\] strs = stream.toArray();
2 Lambda表达式
Lambda用来简化匿名内部类,
不能简化全部匿名内部类,只能简化函数式接口(只有1个抽象方法的接口)的匿名内部类
Lambda与方法引用的作用(为目标对象赋予动作,而不是执行动作)
2.1 Lambda简介
(1) 定义方法
java
private User getUser(Consumer<User> o) {
User u = new User();
o.accept(u);
return u;
}
(2) 调用匿名类
java
// 匿名内部类的使用
// 方式1:先定义再传参
Consumer<User> o = new Consumer<User>() {
public void accept(User user) {
user.setName("zs");
}
};
User u1 = getUser(o);
// 方式2:直接写在参数位置
User u1 = getUser(new Consumer<User>() {
public void accept(User user) {
user.setName("zs");
}
});
Lambda表达式:简写了 new 接口名, 简写了重写函数名。保留参数列表,保留代码体。
java
// Lambda简化后,调用方式
User u1 = getUser(o -> o.setName("zs"));
2.2 函数式接口
注解为@FunctionalInterface的接口一定是函数式接口
2.2.1 Consumer
有参,无返回值
(1) Consumer:void accept(T t); // 1个参数,无返回值
(2) BiConsumer:void accept(T t, U u); // 2个参数,无返回值
2.2.2 Function
有参,有返回值
(1) Function:R apply(T t); // 子类 UnaryOperator
(2) BiFunction:R apply(T t, U u); // 子类 BinaryOperato
2.2.3 Predicate
有参,布尔返回值
(1) Predicate:boolean test(T t);
(2) BiPredicate:boolean test(T t, U u);
2.3 Lambda简写
类 对象 = (int k, int y) -> { returnk + y; }
类 对象 = (User o) -> { o.setName("zs"); }
2.3.1 参数类型省略
(1) 简化前:(intk, inty) -> { return k + y; } // 对象参数 (User o) -> { o.setName("zs"); }
(2) 简化后:(k, y) -> { return k + y; } // 对象参数类型省略 (o) -> { o.setName("zs"); }
2.3.2 参数括号省略
只有一个参数可省略参数括号
(1) 简化前:(o) -> { o.setName("zs"); }
(2) 简化后:o -> { o.setName("zs"); }
2.3.3 代码块省略
只有一行代码可省略大括号与分号
(1) 简化前:(k, y) -> { return k + y**; }**// 对象 o -> { o.setName("zs"); }
(2) 简化后:(k, y) -> return k + y // o -> o.setName("zs")
2.3.4 return省略
只有一行代码可省略return关键字
(1) 简化前:(k, y) -> returnk + y
(2) 简化后:(k, y) -> k + y
2.4 方法引用
前提:函数式接口已经有类实现了,可以直接使用该实现类的方法作成镜像(用::进一步简化lambda表达式)(方法引用,省略了表达式参数及调用方法参数)
2.4.1 构造器引用
lambda只调用构造方法,并且前后参数一致
(1) Lambda写法:(1, 2) -> { new 对象(1, 2) }
(2) 方法引用:对象类名::new
java
Supplier<LambdaTest> slt = LambdaTest::new;
LambdaTest lt = slt.get();
2.4.2 静态方法引用
lambda只调用1个静态方法,并且前后参数一致
(1) Lambda写法:(1, 2) -> { 类.静态方法(1,2) }
(2) 方法引用:类::静态方法 // 前提存在LambdaTest类的 public static void testStatic(String name) {...}方法
java
ltTest(LambdaTest::testStatic);
private void ltTest(Consumer<String> o) { o.accept("name1"); }
2.4.3 对象方法引用
lambda只调用1个实例方法,并且前后参数一致
(1) Lambda写法:(1, 2) -> { 对象.方法(1, 2) }
(2) 方法引用:对象::方法 // 前提存在对象public void testMethod(String name) {...}方法
java
ltTest(obj::testMethod);
private void ltTest(Consumer<String> o) { o.accept("name2"); }
2.4.4 参数方法引用
lambda第一个参数为调用原,剩余参数作为参数
(1) Lambda写法:(Obj1, Obj2) -> {Obj1.方法(Obj2)}
(2) 方法引用:Obj1类名::方法// 前提Obj1类存在方法public void testClass(String name) {..}
java
ltTest(LambdaTest::testClass, lt,"n3");
private static void ltTest(
BiConsumer<LambdaTest,String> o,
LambdaTest lt,
String name) {
o.accept(lt, name);
}