Java8 Stream 流机制和 Lambda 表达式

一、Stream 流介绍与使用场景

Stream 流介绍

  • java8 中的stream 与InputStream和OutputStream是完全不同的概念, stream 是用于对集合迭代器的增强,使之完成能够完成更高效的聚合操作(过滤排序统计分组)或者大批量数据操作。
  • stream 与 Lambda 表达式结合后编码效率大大提高,可读性更强。
    举例如下:
// 获取所有红色苹果的总重量
appleStore.stream().filter(a -> "red".equals(a.getColor()))
.mapToInt(w -> w.getWeight()).sum()
// 基于颜色统计平均重量
appleStore.stream().collect(Collectors.groupingBy(a -> a.getColor(),Collectors.averagingInt(a -> a.getWeight()))).forEach((k, v) -> {System.out.println(k + ":" + v);
});

使用场景

场景一:跨库join的问题

查询一个店铺的订单信息,需要用到订单表与会员表 在传统数据库单一例中 可以通过jon 关联轻松实现,但在分布场景中 这两张表分别存储在于 交易库 和会员库 两个实例中,join不能用。只能在服务端实现其流程如下:

  1. 查询订单表数据
  2. 找出订单中所有会员的ID
  3. 根据会员ID查询会员表信息
  4. 将订单数据与会员数据进行合并

这用传统迭代方法非常繁琐,而这正是stream 所擅长的。示例代码如下:

// 获取所有会员ID 并去重
List<Integer> ids = orders.stream().map(o -> o.getMemberId()).distinct().collect(Collectors.toList());
//  合并会员信息 至订单信息
orders.stream().forEach(o -> {Member member = members.stream().filter(m -> m.getId() == o.getMemberId()).findAny().get();o.setMemberName(member.getName());
});

场景二:N+1 问题

二、Lambda 表达式

Lambda 简介:

  • Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
  • Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
  • Lambda 表达式可以使代码变的更加简洁紧凑。
    匿名类写法
new Thread(new Runnable() {@Overridepublic void run() {System.out.println("hello  world");}
}).start();

Lambda写法

new Thread(() -> System.out.println("hello  world")).start();

在上述例子中编译器会将 “System.out.println(“hello world”)” 编译成Runnable.run 的执行指令。因为 run 方法是Runnable接口的唯一方法,代码中我们无需指明Run方法。如果Runable有多个方法是不能使用Lambda表达示的。

函数式接口:

支持Lambda的接口统称函数式接口。
只有一个抽像方法的接口就是函数式接口,其详细特征如下:

  • 接口中标注了 @FunctionalInterface 注解
  • 接口中只有一个抽像方法会被编译器自动认识成函数式接口
  • 接口中有一个抽像方法,同时包含了Object类的其它抽像方法也会被识别成抽像接口

Lambda表达式三种编写方式:

  1. expression:单条语句表达式
  2. statement:语句块
  3. reference:方法引用

三、Stream 流执行机制

img

流的操作特性

  1. stream不存储数据
  2. stream不改变源数据
  3. stream 不可重复使用

流的操作类型

stream 所有操作组合在一起即变成了管道,管道中有以下两种操作:

  • 中间操作(intermediate): 调用中间操作方法会返回一个新的流。通过连续执行多个操作倒便就组成了Stream中的执行管道(pipeline)。需要注意的是这些管道被添加后并不会真正执行,只有等到调用终值操作之后才会执行。
  • 终值操作(terminal): 在调用该方法后,将执行之前所有的中间操作,获返回结果结束对流的使用
  • 流的执行顺序说明:其每个元素挨着作为参数去调用中间操作及终值操作,而不是遍历完一个方法,再遍历下一个方法。
  • 流的并行操作:调用Stream.parallel() 方法可以将流基于多个线程并行执行

Stream 中的常用API及场景

方法描述操作类型
filter接收一个Boolean表达示来过滤元素中间操作
map将流中元素 1:1 映谢成另外一个元素中间操作
mapToInt将流中元素映谢成int,mapToLong、mapToDouble操作类似目的减少 装箱拆箱带来的损耗中间操作
flatMap如map时返回的是一个List, 将会进一步拆分。详见flatMap示例中间操作
forEach遍历流中所有元素终值操作
sorted排序中间操作
peek遍历流中所有元素 ,如forEach不同在于不会结束流中间操作
toArray将流中元素转换成一个数组返回终值操作
reduce归约合并操作中间操作
collect采集数据,返回一个新的结果 参数说明:Supplier: 采集需要返回的结果BiConsumer<R, ? super T>:传递结果与元素进行合并。BiConsumer<R, R>:在并发执行的时候 结果合并操作。详见 collec示例终值操作
distinct基于equal 表达示去重中间操作
max通过比较函数 返回最大值终值操作
anyMatch流中是否有任一元素满足表达示终值操作
allMatch流中所有元素满足表达示返回true终值操作
noneMatch与allMatch 相反,都不满足的情况下返回 true终值操作
findFirst找出流中第一个元素终值操作
of生成流生成流操作
iterate基于迭代生成流生成流操作
generate基于迭代生成流,与iterate 不同的是不 后一元素的生成,不依懒前一元素生成流操作
concat合并两个相同类型的类生成流操作

举例:

@Testpublic void filterTest() {appleStore.stream().filter(a -> a.getColor().equals("red")).forEach(a -> {System.out.println(a.getColor());});}@Testpublic void mapTest() {appleStore.stream().map(a -> a.getOrigin()).forEach(System.out::println);}@Testpublic void flatMapTest() throws IOException {Stream<String> lines = Files.lines(new File("G:\\git\\tuling-			java8\\src\\main\\java\\com\\tuling\\java8\\stream\\bean\\Order.java").toPath());lines.flatMap(a -> Arrays.stream(a.split(" "))).forEach(System.out::println);}@Testpublic void sortedTest() {appleStore.stream().sorted((a, b) -> a.getWeight() - b.getWeight()).map(a -> a.getWeight()).forEach(System.out::println);}@Testpublic void peekTest() {appleStore.stream().peek(a -> {System.out.println(a.getId());}).map(a -> a.getOrigin()).peek(System.out::println).forEach(a -> {});}@Testpublic void reduceTest() {// 找出最重的那个苹果appleStore.stream().reduce((a, b) -> a.getWeight() > b.getWeight() ? a : b).ifPresent(a -> {System.out.println(a.getWeight());});}@Testpublic void collectTest() {// 将结果转换成id作为key map<Integer,Apple>HashMap<Integer, Apple> map = appleStore.stream().collect(HashMap::new, (m, a) -> m.put(a.getId(), a), (m1, m2) -> m1.putAll(m2));map.forEach((k, v) -> {System.out.println(k);System.out.println(v);});// Map<String,List<Apple>>// 基于颜色分组, 并获取其平均重量}

Collectors 中的常用API及场景

方法描述
toList转换成list
toMap转换成map
groupingBy统计分组
averagingInt求平均值
summingInt求总值
maxBy获取最大值

举例:

// 获得所有颜色苹果的平均重量
@Test
public void groupByTest() {Collector<Apple, ?, Map<String, Double>> groupCollect =Collectors.groupingBy((Apple a) -> a.getColor(), Collectors.averagingInt((Apple a) -> a.getWeight()));appleStore.stream().collect(groupCollect).forEach((k, v) -> {System.out.println(k + ":" + v);});}

流的关闭机制

一般情况使用完流之后不需要调用 close 方法进行关闭,除非是使用channel FileInputStream 这类的操作需要关闭,可调用 java.util.stream.BaseStream#onClose() 添加关闭监听。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/556779.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux guide编译器,GUIDE编译器-GUIDE编程工具-GUIDE编译器下载 v1.0.2官方版-完美下载...

GUIDE编译器是款跨平台的开发环境编程工具&#xff0c;支持C/C 和 Pascal三种语言&#xff0c;具有跨平台、操作简单、跨编程语言和单文件编译调试等特点&#xff0c;为用户提供单文件编译、调试和运行的环境。GUIDE编译器特色1、跨平台&#xff1a; GUIDE 可在 linux 平台和 w…

MySQL事务隔离级别和实现原理

经常提到数据库的事务&#xff0c;那你知道数据库还有事务隔离的说法吗&#xff0c;事务隔离还有隔离级别&#xff0c;那什么是事务隔离&#xff0c;隔离级别又是什么呢&#xff1f;本文就帮大家梳理一下。 MySQL 事务 本文所说的 MySQL 事务都是指在 InnoDB 引擎下&#xff0…

超级全面的MySQL优化面试解析

推荐阅读(点击即可跳转阅读) 1. SpringBoot内容聚合 2. 面试题内容聚合 3. 设计模式内容聚合 4. Mybatis内容聚合 5. 多线程内容聚合 超级全面的MySQL优化面试解析 本文概要 概述 为什么要优化 系统的吞吐量瓶颈往往出现在数据库的访问速度上随着应用程序的运行&#…

mysql linux导入csv主键,MySQL导入csv文件内容到Table及数据库的自增主键设置

写在前面目的是测试将csv文件内容导入到表中, 同时记录一下自增主键的设置.测试采用MySQL8.0.新建表customer_info如下, 未设置主键.修改上表, 添加主键id, 并设置为自增.ALTER TABLE customer_info ADD COLUMN id INT AUTO_INCREMENT NOT NULL PRIMARY KEY;导入步骤1.为了模拟…

mysql 优化方法有哪些?

MySQL索引 MySQL支持诸多存储引擎&#xff0c;而各种存储引擎对索引的支持也各不相同&#xff0c;因此MySQL数据库支持多种索引类型&#xff0c;如BTree索引&#xff0c;哈希索引&#xff0c;全文索引等等。为了避免混乱&#xff0c;本文将只关注于BTree索引&#xff0c;因为这…

Java基础面试题与答案

八种基本数据类型以及包装类 八种基本数据类型默认值&#xff1f;大小&#xff1f;范围区间&#xff1f;包装类的缓存区间&#xff1f; 序号类型名称默认值大小最小值最大值包装类缓冲区间1booleanfalse1B0(false)1(true)Boolean无2byte(byte)01B-128127Byte-128 ~ 1273char‘…

学习vim的linux游戏,PacVim:一个学习 vim 命令的命令行游戏 | Linux 中国

作者 | Sk 译者 | geekpi &#x1f48e; &#x1f48e; 共计翻译&#xff1a;735 篇 贡献时间&#xff1a;1691 天你好&#xff0c;Vim用户&#xff01;今天&#xff0c;我偶然发现了一个很酷的程序来提高 Vim 的使用技巧。Vim 是编写和编辑代码的绝佳编辑器。然而&#x…

Java多线程面试题与答案

线程 线程与进程的区别是什么&#xff1f; 进程指的是应用程序在操作系统中执行的副本&#xff08;系统分配资源的最小单位&#xff09;&#xff0c;线程是程序执行的最小单位&#xff1b;进程使用独立的数据空间&#xff0c;而线程共享进程的数据空间。 线程状态图 多线程会…

JVM面试题与答案

JVM内存布局 JVM在内存布局上可以分为哪些区域&#xff1f; 堆&#xff08;线程共享&#xff09;&#xff1a;GC的主要回收地&#xff0c;包含几乎所有的实例对象、字符串常量池&#xff1b;元空间&#xff08;线程共享&#xff09;&#xff1a;在本地内存分配&#xff0c;包…

md0和md1linux软raid,软RAID管理命令mdadm详解

mdadm是linux下用于创建和管理软件RAID的命令&#xff0c;是一个模式化命令。但由于现在服务器一般都带有RAID阵列卡&#xff0c;并且RAID阵列卡也很廉价&#xff0c;且由于软件RAID的自身缺陷(不能用作启动分区、使用CPU实现&#xff0c;降低CPU利用率)&#xff0c;因此在生产…

Dubbo常见面试题与答案

Dubbo的基础知识 Dubbo的核心架构是怎样的&#xff1f; Registry&#xff1a;注册中心。 负责服务地址的注册与查找&#xff0c;服务的 Provider 和 Consumer 只在启动时与注册中心交互。注册中心通过长连接感知 Provider 的存在&#xff0c;在 Provider 出现宕机的时候&#…

Redis常见面试题与答案

Redis的基本数据类型 Redis有哪些常用的数据类型&#xff1f; String&#xff1a;字符串&#xff08;最常用的缓存&#xff09;Hash&#xff1a;哈希&#xff08;保存对象&#xff09;List&#xff1a;有序列表&#xff08;消息队列&#xff09;Set&#xff1a;无序集合&…

c语言利用文件体写在桌面上,在C语言中怎样新建一个文件夹?

满意答案JacinthLancet推荐于 2017.10.12采纳率&#xff1a;56% 等级&#xff1a;12已帮助&#xff1a;35899人函数名: mkdir功 能: 建立一个目录(文件夹)用 法: int mkdir(char *pathname);程序例: (在win-tc和Dev-c下运行通过)#include #include #include int main(void){…

MySQL常见面试题与答案

存储引擎 InnoDB的主要特点是什么&#xff1f; MySQL5.5版本之后的默认存储引擎&#xff1b;支持事务&#xff1b;支持行级锁&#xff1b;支持MVCC&#xff1b;支持聚集索引方式存储数据。 InnoDB与MyISAM的区别&#xff1f; 存储引擎MyISAMInnoDB存储结构MyISAM在磁盘上存…

Spring 异常处理三种方式

Spring 异常处理三种方式 异常处理方式一. ExceptionHandler异常处理方式二. 实现HandlerExceptionResolver接口异常处理方式三. ControllerAdviceExceptionHandler三种方式比较说明(强烈推荐各位看一下&#xff0c;我觉得自己总结的比较多&#xff0c;嘿嘿&#xff0c;不对之…

Netty常见面试题 与 答案

Netty基础知识 什么是Netty&#xff1f; Netty 是一款用于高效开发网络应用的 NIO 网络框架&#xff0c;它大大简化了网络应用的开发过程&#xff1b; 封装了JDK底层的NIO模型&#xff0c;提供高度可用的API&#xff0c;用于快速开发高性能服务端和客户端&#xff1b;精心设计…

CAS单点登录详细流程

一、CAS简介和整体流程 CAS 是 Yale 大学发起的一个开源项目&#xff0c;旨在为 Web 应用系统提供一种可靠的单点登录方法&#xff0c;CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目。CAS 具有以下特点&#xff1a; 【1】开源的企业级单点登录解决方案。 【2】CAS Server 为…

android 图片自动拉伸,解决关于ImageView自适应的问题(拉伸变形,图片模糊)

今天接手一个项目发现有个地方的图片显示非常小&#xff0c;而且还不够清晰&#xff0c;也没办法自适应屏幕的显示&#xff0c;非常的影响美观&#xff0c;于是 就像这优化一下。先看看优化前的效果和优化后的效果。修复后修复前布局文件修复前&#xff1a;修复前布局文件修复后…

redisTemplate.opsForValue()中方法讲解

查看源码可以看到redisTemplate.opsForValue()中的方法都定义在ValueOperations<K, V> 中&#xff0c;该接口中一共有17个方法&#xff1a; public interface ValueOperations<K, V> {void set(K key, V value);void set(K key, V value, long timeout, TimeUnit …

spring boot配置dubbo(properties)

spring boot与dubbo配置(properties) dubbo和zookeeper配合使用&#xff0c;具体的它们之间的配置这里不说了。 一、spring boot与dubbo配置有两种方式&#xff1a; 1&#xff09;spring boot在自己的配置文件application.properties 配置dubbo。&#xff08;本篇主要说这个&…