【函数式编程】StreamAPI

StreamAPI

streamApi是Java8引入的一个接口,它与lamda表达式浑然天成的,可以算是lambda表达式的完美搭档。

Stream对象里有很多方法,传入的参数都是函数式接口,去源码看看

swift 复制代码
public interface Stream<T> extends BaseStream<T, Stream<T>> {
    Stream<T> filter(Predicate<? super T> predicate);
    <R> Stream<R> map(Function<? super T, ? extends R> mapper);

可以看到它里面的方法的参数有Predicate接口, Function接口等,你进去看看,会发现它们都是函数式接口,而且方法返回的也是Stream对象,所以可以多次操作

函数式接口又支持Lambda,所以说Stream是Lambda表达式的最佳搭档不过分吧。

Stream API的主要作用

  1. 集合对象提供了一种查询和转化的新方式。
  2. 引入了函数式编程的概念,使得操作更加简洁灵活。
  3. 支持并行(parallel) 提高运行效率,一般来说,for循环是更快的,但是Stream支持并行,大任务分为小任务去执行;因此,很大的集合对象肯定是Stream处理更快的。

这个API主要在能迭代的对象里使用,比如实现了Collection接口的类。

我觉得他极大的简化了集合代码遍历及其操作。


举个例子: 我现在有一个集合,我要找到姓名为a开头的人,然后在这些以a开头的人中的倒序打印三个名字。

一般写法

csharp 复制代码
public class Solution {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("abc");
        list.add("bcd");
        list.add("acd");
        list.add("dbc");
        list.add("obc");
        list.add("abf");
        list.add("abz");

        ArrayList<String> res1 = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            if(list.get(i).startsWith("a")){
                res1.add(list.get(i));
            }
        }
        res1.sort((a, b) -> CharSequence.compare(b, a));
        for (int i = 0; i < 3; i++) {
            System.out.println(res1.get(i));
        }
    }
}

Stream流写法

scss 复制代码
list.stream().filter((o)->o.startsWith("a")).sorted((a,b)-> CharSequence.compare(b,a)).
        limit(3).forEach(System.out::println);

Stream运行原理

大家可能很好奇,为啥使用之后就可以很简单的操作集合元素。

我们用它的map方法举例。

当我们对集合元素进行stream()方法时,会获得一个实现了Stream()接口的对象,使用Stream指向该对象,该对象里的map实现形如:

该Stream()会拿到集合的迭代器引用,不断的迭代,然后对里面的对象进行mapper操作,当然,这个mapper操作是我们在函数外面传入的lambda表达式。

该方法会对集合里的每一个元素进行操作,同时返回一个Stream对象,可以进行进一步的处理。

总的来说,就是每次操作都创建一个ArrayList,然后将操作之后的结果放进这个list,然后返回它的stream流。

一些常用的函数使用

count

作用: 用于获取集合的数量

参数: 无

返回值: long

skip

作用: 跳过n个集合元素

参数: long size

返回值: Stream流

map

stream运行原理里面介绍了map:

作用: 对每一个集合函数进行操作

参数:Function函数式接口

返回值: Stream流

使用:

c 复制代码
list.stream().map((o)-> o + "hhh");

forEach

作用: 遍历每一个集合元素,然后进行一些操作。

参数: Consumer 函数式接口

返回值: void

源码:

使用:

scss 复制代码
list.stream().forEach(o-> System.out.println(o));

使用这个方法之后就不能再调用方法了,因为返回值为void。

filter

作用: 过滤集合中一些数据

参数: Predicate函数式接口

返回值: Stream流

源码:

使用:

scss 复制代码
list.stream().filter((o)->o.startsWith("a"));

reduce

作用: 集合中的数据的累积操作

返回值: Stream流

它有多个重载函数,下面有具体的介绍: Stream的reduce的使用_stream.reduce-CSDN博客

总结

  1. stream流对于继承Collection集合的类的操作很是方便
  2. 对于大数组的操作效率更高
  3. stream与lambda表达式天生适配
相关推荐
凌冰_11 分钟前
IDEA2023 SpringBoot整合MyBatis(三)
spring boot·后端·mybatis
码农飞飞19 分钟前
深入理解Rust的模式匹配
开发语言·后端·rust·模式匹配·解构·结构体和枚举
一个小坑货21 分钟前
Rust 的简介
开发语言·后端·rust
monkey_meng1 小时前
【遵守孤儿规则的External trait pattern】
开发语言·后端·rust
Estar.Lee1 小时前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
新知图书2 小时前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
盛夏绽放2 小时前
Node.js 和 Socket.IO 实现实时通信
前端·后端·websocket·node.js
Ares-Wang2 小时前
Asp.net Core Hosted Service(托管服务) Timer (定时任务)
后端·asp.net
uzong3 小时前
7 年 Java 后端,面试过程踩过的坑,我就不藏着了
java·后端·面试
Rverdoser4 小时前
RabbitMQ的基本概念和入门
开发语言·后端·ruby