函数式编程优势“函数第一位”,即函数可以出现在任何地方。

可以把函数作为参数传递给另一个函数,还可以将函数作为返回值。

让代码的逻辑更清晰更优雅。

减少了可变量(Immutable Variable)的声明,程序更为安全。

支持惰性计算。

Lambda语法三部分一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数

一个箭头符号:->

方法体,可以是表达式和代码块,方法体函数式接口里面方法的实现,如果是代码块,则必须用{}来包裹起来,且需要一个return 返回值,但有个例外,若函数式接口里面方法返回值是void,则无需{}。例如:

(parameters) -> expression 或者 (parameters) -> { statements; }

方法引用是lambda表达式的一个简化写法,所引用的方法其实是lambda表达式的方法体实现,语法也很简单,左边是容器(可以是类名,实例名),中间是“::”,右边是相应的方法名。如下所示:

ObjectReference::methodName

一般方法的引用格式是:如果是静态方法,则是ClassName::methodName。如 Object ::equals

如果是实例方法,则是Instance::methodName。如Object obj=new Object();obj::equals;

构造函数.则是ClassName::new

Stream是什么

Stream是Java8中新加入的api,更准确的说: Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作 。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。

以前我们处理复杂的数据只能通过各种for循环,不仅不美观,而且时间长了以后可能自己都看不太明白以前的代码了,但有Stream以后,通过filter,map,limit等等方法就可以使代码更加简洁并且更加语义化。 Stream的效果就像上图展示的它可以先把数据变成符合要求的样子(map),吃掉不需要的东西(filter)然后得到需要的东西(collect)。

Stream操作分类

Stream上的所有操作分为两类:中间操作和结束操作,中间操作只是一种标记,只有结束操作才会触发实际计算。中间操作又可以分为无状态的(Stateless)和有状态的(Stateful),无状态中间操作是指元素的处理不受前面元素的影响,而有状态的中间操作必须等到所有元素处理之后才知道最终结果,比如排序是有状态操作,在读取所有元素之前并不能确定排序结果;结束操作又可以分为短路操作和非短路操作,短路操作是指不用处理全部元素就可以返回结果,比如找到第一个满足条件的元素。之所以要进行如此精细的划分,是因为底层对每一种情况的处理方式不同。

Stream API等价实现

求出字符串集合中所有以字母A开头字符串的最大长度

int longest = 0;

for(String str : strings){

if(str.startsWith("A")){// 1. filter(), 保留以A开头的字符串

int len = str.length();// 2. mapToInt(), 转换成长度

longest = Math.max(len, longest);// 3. max(), 保留最长的长度

}

}

int longest = strings.stream()

.filter(str -> str.startsWith("A"))

.mapToInt(str -> str.length())

//.mapToInt(String::length)

.max();

Stream串行与并行

Stream可以分为串行与并行两种,串行流和并行流差别就是单线程和多线程的执行。 default Stream stream() : 返回串行流 default Stream parallelStream() : 返回并行流 stream()和parallelStream()方法返回的都是java.util.stream.Stream类型的对象,说明它们在功能的使用上是没差别的。唯一的差别就是单线程和多线程的执行。

Stream性能总结

1.对于简单操作,比如最简单的遍历,Stream串行API性能明显差于显示迭代,但并行的Stream API能够发挥多核特性。

2.对于复杂操作,Stream串行API性能可以和手动实现的效果匹敌,在并行执行时Stream API效果远超手动实现。

所以,如果出于性能考虑:对于简单操作推荐使用外部迭代手动实现。

对于复杂操作,推荐使用Stream API。

在多核情况下,推荐使用并行Stream API来发挥多核优势。

单核情况下不建议使用并行Stream API。 如果出于代码简洁性考虑,使用Stream API能够写出更短的代码。即使是从性能方面说,尽可能的使用Stream API也另外一个优势,那就是只要Java Stream类库做了升级优化,代码不用做任何修改就能享受到升级带来的好处。

Stream 来源

所有流计算都有一种共同的结构:它们具有一个流来源、0 或多个中间操作,以及一个终止操作。流的元素可以是对象引用 (Stream),也可以是原始整数 (IntStream)、长整型 (LongStream) 或双精度 (DoubleStream)。

因为 Java 程序使用的大部分数据都已存储在集合中,所以许多流计算使用集合作为它们的来源。JDK 中的 Collection 实现都已增强,可充当高效的流来源。但是,还存在其他可能的流来源,比如数组、生成器函数或内置的工厂(比如数字范围),而且可以编写自定义的流适配器,以便可以将任意数据源充当流来源。如上图中一些流生成方法。

Stream 操作

中间操作负责将一个流转换为另一个流,中间操作包括 filter()(选择与条件匹配的元素)、map()(根据函数来转换元素)、distinct()(删除重复)、limit()(在特定大小处截断流)和 sorted()。一些操作(比如 mapToInt())获取一种类型的流并返回一种不同类型的流。

中间操作始终是惰性的:调用中间操作只会设置流管道的下一个阶段,不会启动任何操作。重建操作可进一步划分为无状态 和有状态 操作。无状态操作(比如 filter() 或 map())可独立处理每个元素,而有状态操作(比如 sorted() 或 distinct())可合并以前看到的影响其他元素处理的元素状态。

数据集的处理在执行终止操作时开始,比如缩减(sum() 或 max())、应用 (forEach()) 或搜索 (findFirst()) 操作。终止操作会生成一个结果或副作用。执行终止操作时,会终止流管道,如果您想再次遍历同一个数据集,可以设置一个新的流管道。如下给出了一些终止流操作。

Stream 流与集合比较

集合是一种数据结构,它的主要关注点是在内存中组织数据,而且集合会在一段时间内持久存在。 流的关注点是计算,而不是数据。流没有为它们处理的元素提供存储空间,而且流的生命周期更像一个时间点 — 调用终止操作。 不同于集合,流也可以是无限的(Stream.generate、Stream.iterate);相应地,一些操作(limit()、findFirst())是短路,而且可在无限流上运行有限的计算。 程序 = 数据结构 + 算法,集合即数据结构,流操作相当于算法。

数据形式:集合是一个内存中的数据结构,它包含数据结构中目前所有的值——集合中的每个元素都得先算出来才能添加到集合中。(你可以往集合里加东西或者删东西,但是不管什么时候,集合中的每个元素都是放在内存里的,元素都得先算出来才能成为集合的一部分。) 相比之下,流则是在概念上固定的数据结构(你不能添加或删除元素),其元素则是按需计算的。

迭代方式:使用Collection接口需要用户去做迭代(比如用for-each),这称为外部迭代。相反,Streams库使用内部迭代——它帮你把迭代做了,还把得到的流值存在了某个地方,你只要给出一个函数说要干什么就可以了。Steams库的内部迭代可以自动选择一种适合你硬件的数据表示和并行实现。

Stream 基本使用

filter筛选(中间操作)

输出:4,5

List integerList = Arrays.asList(1, 1, 2, 3, 4, 5);

Stream stream = integerList.stream().filter(i -> i > 3);

distinct去重(中间操作)

输出:1,2,3,4,5

List integerList = Arrays.asList(1, 1, 2, 3, 4, 5);

Stream stream = integerList.stream().distinct();

limit限制(中间操作)

输出:1,1,2

List integerList = Arrays.asList(1, 1, 2, 3, 4, 5);

Stream stream = integerList.stream().limit(3);

skip跳过(中间操作)

输出:2,3,4,5

List integerList = Arrays.asList(1, 1, 2, 3, 4, 5);

Stream stream = integerList.stream().skip(2);

map流映射(中间操作)

输出:6, 7, 2, 6

List stringList = Arrays.asList("Java 8", "Lambdas", "In", "Action");

Stream stream = stringList.stream().map(String::length);

flatMap流转换(中间操作)

输出:1, 2, 3, 4

将一个流中的每个值都转换为另一个流

List> lists = new ArrayList>() {{

add(Arrays.asList(1, 2));

add(Arrays.asList(3, 4));

}};

Stream stream = lists.stream().flatMap(List::stream);

//Stream stream = lists.stream().flatMap(list -> list.stream());

allMatch匹配所有(中间操作)

输出:

List integerList = Arrays.asList(1, 2, 3, 4, 5);

if (integerList.stream().allMatch(i -> i > 3)) {

System.out.println("值都大于3");

}

noneMatch全部不匹配(中间操作)

输出:

List integerList = Arrays.asList(1, 2, 3, 4, 5);

if (integerList.stream().noneMatch(i -> i > 3)) {

System.out.println("值都小于3");

}

anyMatch匹配其中一个(中间操作)

输出:存在大于3的值

List integerList = Arrays.asList(1, 2, 3, 4, 5);

if (integerList.stream().anyMatch(i -> i > 3)) {

System.out.println("存在大于3的值");

}

findFirst查找第一个(终端操作)

输出:4

List integerList = Arrays.asList(1, 2, 3, 4, 5);

Optional result = integerList.stream().filter(i -> i > 3).findFirst();

findAny随机查找一个(终端操作)

输出:存在大于3的值

和findFirst操作相比,并行流优势更大

List integerList = Arrays.asList(1, 2, 3, 4, 5);

if (integerList.stream().findAny(i -> i > 3)) {

System.out.println("存在大于3的值");

}

Stream 常用统计

List ints = Arrays.asList(1, 1, 2, 2, 3);

//统计流中元素个数

ints.stream().count();

ints.stream().collect(Collectors.counting());

//获取流中最小值

ints.stream().min(Integer::compareTo);

ints.stream().collect(Collectors.minBy(Integer::compareTo));

//获取流中最大值

ints.stream().max(Integer::compareTo);

ints.stream().collect(Collectors.maxBy(Integer::compareTo));

//求和

ints.stream().mapToInt(Integer::intValue).sum();

ints.stream().collect(Collectors.summingInt(Integer::intValue));

ints.stream().reduce(0, Integer::sum);

//平均值

ints.stream().collect(Collectors.averagingInt(Integer::intValue));

//通过summarizingInt同时求总和、平均值、最大值、最小值

ints.stream().collect(Collectors.summarizingInt(Integer::intValue));

Stream 终端操作(collect)

List ints = Arrays.asList(1, 1, 2, 2, 3);

//返回List

ints.stream().collect(Collectors.toList());

//返回Set

ints.stream().collect(Collectors.toSet());

//返回Map

ints.stream().collect(Collectors.toMap(k -> k, v -> v, (v1, v2) -> v1));

//group分组

ints.stream().collect(Collectors.groupingBy(k -> k));

//partitioningBy分区

ints.stream().collect(Collectors.partitioningBy(k -> k % 2 == 0));

Stream参考文献

java8函数式编程 视频_快速掌握Java8 Stream函数式编程技巧相关推荐

  1. 好好搭搭机器人编程视频_小学生“玩转”机器人 自学编程制作40多个作品

    在很多人眼里,机器人十分高端,制作机器人更是科技工作者的事.不过在11岁的小学生龙旭阳眼里,机器人制作已不再神秘.自学编程一年多,仿制不到3个月,龙旭阳就已将600多个制作机器人的零部件玩转自如了.从 ...

  2. ironbot智能编程机器人_边玩边学,编程启蒙,IronBot机器人套件视频图文评测

    前言 当今世界充满竞争和挑战,你的对手可能不是人.早在2015年,教育部就颁发了指导意见,鼓励以编程为核心的,包括科学(S).技术(T).工程(E).艺术和航空(A),以及数学(M)五个方面的&quo ...

  3. wedo巡线机器人编程教程_这是一个机器人和编程的时代

    图中在草地上自在奔跑的机器人是波士顿动力公司(BostonDynamics) 开发的类人双足机器人Atlas,由麻省理工(MIT)电子工程与计算机科学系的教授马克·雷波特在1992年创立,一直致力于将 ...

  4. halcon机器视觉算法原理与编程实战_快速弄懂机器学习里的集成算法:原理、框架与实战...

    作者:  博观厚积 简书专栏:https://www.jianshu.com/u/2f376f777ef1 1. 关于集成学习算法 集成学习算法,通俗地讲就是:三个臭皮匠,顶个诸葛亮,这在很多地方都有 ...

  5. wallpaper怎么导入视频_快速制作视频字幕,我们推荐这款可视化字幕软件!

    大家平时在使用诸如pr,会声会影,或者爱剪辑等视频编辑软件制作字幕时会不会觉得很麻烦,一点都不方便呢?亦或是大家苦苦寻找,却怎么都找不到合适的字幕制作软件. 那么到底有没有即高效又方便快捷的字幕制作软 ...

  6. python优雅编程视频_日常 Python 编程优雅之道

    3 个可以使你的 Python 代码更优雅.可读.直观和易于维护的工具. Python 提供了一组独特的工具和语言特性来使你的代码更加优雅.可读和直观.为正确的问题选择合适的工具,你的代码将更易于维护 ...

  7. 好好搭搭机器人编程视频_机器人编程搭建 | 乐创世界学员作品展示第4期!

    乐创世界学员-梅好 课程主题:<翻斗车> 认知目标:①了解翻斗车的相关知识②了解翻斗车的结构特③了解翻斗车的作用 能力目标:①培养空间想象力②培养动手能力③了解翻斗车的结构④设计搭建一个翻 ...

  8. java8无法安装怎么办_关于安装java8 运行 java -version 失败的解决办法

    我使用的操作系统是 centos7 安装的java版本是在官方网站下载的 jdk-8u181-linux-i586.tar.gz /etc/profile 配置如下 : export JAVA_HOM ...

  9. 网易5天python编程课_网易云课堂上自学编程?

    (一) 不是大佬.题主问的是有没有必要按照网易云课堂上的大一到大四的全部课程学习一遍? 强答一波:没有必要. 题主这么提问,无非就是想减少自己的试错成本,在这里分享一些我这段时间以来的学习经历.每个人 ...

最新文章

  1. 阿里程序员连续两次绩效3.25!大老板威胁要开除他!还不给赔偿金!问大家该如何维权?...
  2. R语言机器学习Caret包(Caret包是分类和回归训练的简称)、数据划分、数据预处理、模型构建、模型调优、模型评估、多模型对比、模型预测推理
  3. linux下批量添加新用户
  4. jenkins配置python脚本参数_jenkins配置python脚本定时任务过程图解
  5. linux java字符集编码_Java字符集编码
  6. 小屏党失望!iPhone 13四款机型,mini版没了
  7. 虚函数virtual
  8. dio设置自定义post请求_Flutter中的http网络请求
  9. py2exe将python打包成exe
  10. Xcode证书错误 Provisioning profile does not support the Associated Domains capability
  11. Wordpress源码文件详解
  12. xp系统怎么创建服务器新用户,xp系统ftp服务器创建用户
  13. 台式计算机红外线端口,台式电脑的红外线端口在哪?
  14. Place Holder 方法
  15. Linux命令分隔符
  16. Pytorch | 学习笔记(二)
  17. uniapp返回上一级选择性刷新数据,不重新加载页面
  18. 洛谷 P1359 租用游艇
  19. HDFS高可用配置及其高可用集群搭建
  20. PIE-engine 教程 ——MODIS影像去云教程(山西省为例)

热门文章

  1. 人工构造迭代次数高度简并的神经网络训练集
  2. 用特征光谱分类神经网络
  3. 用两个矩阵的点积计算神经网络的迭代次数 2-8
  4. 8. An Introduction to MCMC for Machine Learning (3)
  5. python idle编辑的代码文件拓展名是_Python IDLE编辑器打开后缀名为.py的文件
  6. 微信小程序码buffer转为图片php,微信小程序将网络图片转成base64数据
  7. STM32 基础系列教程 45 - FSMC_LCD_Touch
  8. ubuntu18.04安装VCS+verdi错误集锦
  9. DFT泄露问题和DFT的频率轴表示方法(第三章离散傅里叶变换(3.8,3.13.4)学习笔记)
  10. 【S操作】一个简单粗暴易用的远程调试方案——OTA http update