Java学习笔记十三(Stream与Lambda)

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);
}
相关推荐
爱三盖浇饭1 小时前
挑战从零开始学习Kafka2: Kafka 常见问题解决方案
学习·kafka
dtq04242 小时前
数据结构 - 线性表 - 双向链表
c语言·数据结构·学习
M78佐菲8 小时前
Linux学习笔记:TCP协议
linux·笔记·学习·tcp/ip·算法
噜~噜~噜~9 小时前
操作系统笔记-2.3.5.1.1生产者-消费者问题
笔记·操作系统
yi.Ist9 小时前
数据定义语言-DDL操作
数据库·学习·mysql·oracle·大海豚
骐骥113 小时前
学习:javaScriptProxy和registerJavaScriptProxy有什么区别,能注册多少个对象
学习·鸿蒙
Huathy-雨落江南,浮生若梦13 小时前
Caddy 学习笔记 - 反向代理与 IP 封禁
笔记·学习·tcp/ip
谢白羽14 小时前
SGLang的AWQ量化笔记
笔记·python·sglang
噜~噜~噜~14 小时前
操作系统笔记-2.3.5.2 读者-写者问题
笔记·操作系统