【Java进阶】Java Lambda 表达式、Stream API完整梳理

一、Lambda表达式

Lambda 表达式是一种匿名函数,它可以用来定义函数式接口的实现。Lambda 表达式可以用来简化代码,提高代码的可读性和可维护性。

1、Lambda 表达式

1.1、语法介绍

Lambda 表达式的语法如下:

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

Lambda表达式由以下几个部分组成:

  • 参数列表(parameters):Lambda表达式可以有零个或多个参数。如果有多个参数,使用逗号将它们分隔开。参数的类型可以显式指定,也可以通过上下文推断得出。

  • 箭头符号(->):箭头符号用于分隔参数列表和Lambda表达式的主体。

  • 表达式(expression)或语句块(statements):Lambda表达式的主体可以是一个表达式或一个代码块。如果主体是一个表达式,则可以直接返回该表达式的结果。如果主体是一个代码块,则需要使用大括号将代码块括起来,并且可能需要使用return语句来返回结果。

Lambda 表达式是一种匿名函数,它可以用来定义函数式接口的实现。Lambda 表达式可以用来简化代码,提高代码的可读性和可维护性。

1.2、Lambda表达式特性

除了Java版本的要求外,Lambda表达式只能用于函数式接口。

  1. 函数式接口:Lambda表达式只能用于函数式接口,即只有一个抽象方法的接口。函数式接口可以使用@FunctionalInterface注解进行标记,以确保只有一个抽象方法。
@FunctionalInterface
interface MyInterface {void myMethod();
}public class Main {public static void main(String[] args) {MyInterface myInterface = () -> System.out.println("Hello, Lambda!");myInterface.myMethod();}
}

在上面的示例中,我们定义了一个函数式接口MyInterface,它只有一个抽象方法myMethod。然后,我们使用Lambda表达式来实现这个接口,并在myMethod方法中打印一条消息。最后,我们创建了一个接口实例并调用myMethod方法。

  1. 上下文推断:Lambda表达式的参数类型可以通过上下文推断得出,无需显式指定。这是Java 8引入的类型推断机制的一部分。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));

在这个例子中,Lambda表达式name -> System.out.println(name)被传递给forEach方法。编译器会根据forEach方法的参数类型推断出Lambda表达式的参数类型为String。

  1. 方法引用:Lambda表达式可以使用方法引用来简化代码,双冒号(:😃。方法引用是指直接引用已有方法的方式,可以通过类名、对象实例或超类来引用方法。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");names.stream().map(String::toUpperCase).forEach(System.out::println);

在这个例子中,String::toUpperCase是一个方法引用,它引用了String类的toUpperCase方法。在map方法中,每个元素都会被转换为大写。然后,使用forEach方法将转换后的结果打印出来。方法引用使代码更加简洁,不需要编写Lambda表达式来调用toUpperCase方法。

1.3、方法引用,双冒号(::)

在Lambda表达式中,双冒号(::)是一种特殊的语法,用于引用方法或构造函数。它可以用于以下几种情况:

  1. 方法引用:使用双冒号(::)来引用一个已经存在的方法。例如,假设有一个函数式接口Function,它有一个抽象方法apply,可以使用方法引用来引用一个已经存在的方法作为apply的实现。例如:
Function<String, Integer> function = Integer::parseInt;

这里,Integer::parseInt表示引用了Integer类的静态方法parseInt作为apply方法的实现。

  1. 构造函数引用:使用双冒号(::)来引用一个构造函数。例如,假设有一个函数式接口Supplier,它有一个抽象方法get,可以使用构造函数引用来引用一个构造函数作为get方法的实现。例如:
Supplier<List<String>> supplier = ArrayList::new;

这里,ArrayList::new表示引用了ArrayList类的构造函数作为get方法的实现。

  1. 数组引用:使用双冒号(::)来引用一个数组。例如,可以使用int[]::new来引用一个整型数组的构造函数。

2、Lambda 表达式最佳实践

2.1、简单使用示例

以下是一些使用 Lambda 表达式的示例:

// 作为方法的参数
List<String> names = Arrays.asList("Alice", "Bob", "Carol");
names.sort((a, b) -> b.compareTo(a));// 作为构造函数的参数
Button button = new Button(() -> System.out.println("Click"));// 作为成员变量的初始值
Map<String, String> map = new HashMap<>();
map.put("key", "value");// 作为局部变量的初始值
int sum = names.stream().mapToInt(String::length).sum();

Lambda 表达式可以提高代码的可读性和可维护性,因此在编写 Java 代码时,我们应该尽可能使用 Lambda 表达式。

2.2、Lambda表达式最佳实践

以下是使用Lambda表达式的一些最佳实践:

  1. 使用合适的函数式接口:Lambda表达式需要与函数式接口一起使用。函数式接口是只包含一个抽象方法的接口。在选择函数式接口时,确保它与Lambda表达式的参数和返回类型匹配。

  2. 保持Lambda表达式简洁:Lambda表达式的主要目的是使代码更加简洁和易读。因此,应尽量避免编写过于复杂的Lambda表达式。如果Lambda表达式变得过于冗长或复杂,可以考虑将其提取为一个独立的方法或使用方法引用。

  3. 使用方法引用:方法引用是Lambda表达式的一种简化形式,可以使代码更加简洁和易读。如果Lambda表达式只是简单地调用一个已经存在的方法,可以考虑使用方法引用来代替Lambda表达式。

  4. 避免副作用:Lambda表达式应该是无副作用的,即不会对外部状态产生影响。这有助于提高代码的可读性和可维护性。如果Lambda表达式需要修改外部状态,应该使用其他方式来处理,例如使用局部变量或实例变量。

  5. 使用类型推断:在Lambda表达式中,编译器可以根据上下文推断参数类型。因此,可以省略参数类型的显式声明,使代码更加简洁。但是,如果Lambda表达式的参数类型不明确或不容易理解,最好显式声明参数类型,以提高代码的可读性。

  6. 使用Lambda表达式的流式操作:Lambda表达式与流式操作(Stream API)结合使用可以实现更加简洁和功能强大的代码。流式操作提供了一种流畅的方式来处理集合数据,可以使用Lambda表达式来定义各种操作,如过滤、映射、排序等。

总的来说,使用Lambda表达式应该注重代码的简洁性、可读性和可维护性。合理选择函数式接口、使用方法引用、避免副作用以及充分利用类型推断和流式操作等技巧,可以使Lambda表达式的使用更加高效和优雅。

二、Steam API

Java 8 引入了新的 Stream API,它提供了一种更简单、更高效的方式来处理集合。Stream API 是一个函数式编程 API,它允许我们对集合中的元素进行各种操作,而无需使用传统的 for 循环。

Stream API 的核心是 Stream 对象,它表示一个元素序列。Stream 可以由集合创建,也可以由其他 Stream 创建。Stream 可以通过各种方式进行操作,包括过滤、映射、聚合和收集。

1、Stream API 常见使用

Stream API 的使用非常简单。要创建一个 Stream,我们可以使用集合的 stream() 方法。例如,以下代码创建了一个包含数字 1 到 10 的 Stream:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Stream<Integer> stream = numbers.stream();

Stream 可以通过各种方式进行操作。最常见的操作是过滤和映射。过滤操作用于从 Stream 中选择满足某些条件的元素。例如,以下代码使用 filter() 方法从 Stream 中选择所有偶数:

Stream<Integer> evenNumbers = stream.filter(n -> n % 2 == 0);

映射操作用于将 Stream 中的元素转换为另一种类型的元素。例如,以下代码使用 map() 方法将 Stream 中的数字转换为字符串:

Stream<String> strings = stream.map(n -> String.valueOf(n));

Stream 还可以通过聚合操作来计算结果。聚合操作用于将 Stream 中的元素汇总到一个单一的值。例如,以下代码使用 sum() 方法计算 Stream 中所有元素的总和:

int sum = stream.sum();

Stream 还可以通过收集操作将结果保存到集合中。例如,以下代码使用 collect() 方法将 Stream 中的元素收集到一个列表中:

List<Integer> list = stream.collect(Collectors.toList());

Stream API 提供了一种非常简单、高效的方式来处理集合。它可以帮助我们编写更简洁、更可读的代码。

2、Stream API 使用示例

以下是一些使用 Stream API 的示例:

  • 计算集合中所有元素的总和:
int sum = numbers.stream().mapToInt(n -> n).sum();
  • 计算集合中所有元素的平均值:
double average = numbers.stream().mapToInt(n -> n).average().getAsDouble();
  • 查找集合中最大的元素:
Optional<Integer> max = numbers.stream().max(Comparator.comparing(n -> n));
  • 查找集合中所有的偶数:
Stream<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0);
  • 将集合中的元素转换为字符串:
Stream<String> strings = numbers.stream().map(n -> String.valueOf(n));
  • 将集合中的元素收集到一个列表中:
List<Integer> list = numbers.stream().collect(Collectors.toList());
  • 将集合中的元素保存到文件中:
numbers.stream().forEach(n -> System.out.println(n));

3、Stream API 核心方法

下面常用的Stream API方法:

方法描述类型使用示例
filter(Predicate<T> predicate)过滤流中的元素,只保留满足条件的元素中间操作stream.filter(x -> x > 5)
map(Function<T, R> mapper)对流中的每个元素应用一个函数,并将结果映射为一个新的流中间操作stream.map(x -> x * 2)
flatMap(Function<T, Stream<R>> mapper)对流中的每个元素应用一个函数,并将结果扁平化为一个新的流中间操作stream.flatMap(x -> Stream.of(x, x + 1))
distinct()去除流中的重复元素中间操作stream.distinct()
sorted()对流中的元素进行排序中间操作stream.sorted()
limit(long maxSize)限制流中元素的数量不超过指定的最大值中间操作stream.limit(10)
skip(long n)跳过流中的前n个元素中间操作stream.skip(5)
forEach(Consumer<T> action)对流中的每个元素执行指定的操作终止操作stream.forEach(System.out::println)
collect(Collector<T, A, R> collector)将流中的元素收集到一个可变容器中,如List、Set或Map终止操作stream.collect(Collectors.toList())
reduce(BinaryOperator<T> accumulator)将流中的元素按照指定的操作进行归约,得到一个结果终止操作stream.reduce(0, (a, b) -> a + b)
anyMatch(Predicate<T> predicate)检查流中是否存在满足条件的元素终止操作stream.anyMatch(x -> x > 5)
allMatch(Predicate<T> predicate)检查流中的所有元素是否都满足条件终止操作stream.allMatch(x -> x > 0)
noneMatch(Predicate<T> predicate)检查流中是否没有任何元素满足条件终止操作stream.noneMatch(x -> x < 0)
findFirst()返回流中的第一个元素终止操作stream.findFirst()
findAny()返回流中的任意一个元素终止操作stream.findAny()
count()返回流中的元素数量终止操作stream.count()
min(Comparator<T> comparator)返回流中的最小元素终止操作stream.min(Comparator.naturalOrder())
max(Comparator<T> comparator)返回流中的最大元素终止操作stream.max(Comparator.naturalOrder())

这些方法根据其功能和使用方式可以分为两种类型:中间操作和终止操作。中间操作返回一个新的流,可以被链式调用,而终止操作会产生一个最终结果或副作用。根据具体的需求,可以根据需要组合使用这些方法来处理和操作流中的元素。

4、Stream 可以配合哪些类使用

Stream 可以配合多种类使用,包括但不限于以下类:

  1. Collection 接口:Stream 可以通过 Collection 接口的 stream() 方法来创建。
List<String> names = Arrays.asList("Alice", "Bob", "Carol");
Stream<String> stream = names.stream();
  1. Arrays 类:Stream 可以通过 Arrays 类的 stream() 方法来创建。
int[] numbers = {1, 2, 3, 4, 5};
IntStream stream = Arrays.stream(numbers);
  1. BufferedReader 类:Stream 可以通过 BufferedReader 类的 lines() 方法来创建。
BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
Stream<String> lines = reader.lines();
  1. IntStream、LongStream、DoubleStream 类:这些类提供了特定类型的 Stream,可以用于处理基本类型的元素。
IntStream intStream = IntStream.of(1, 2, 3, 4, 5);
LongStream longStream = LongStream.range(1, 10);
DoubleStream doubleStream = DoubleStream.generate(Math::random);
  1. Files 类:Stream 可以通过 Files 类的 lines() 方法来读取文件内容并创建。
Stream<String> lines = Files.lines(Paths.get("file.txt"));
  1. Pattern 类:Stream 可以通过 Pattern 类的 splitAsStream() 方法来将字符串拆分为 Stream。
Pattern pattern = Pattern.compile("\\s+");
Stream<String> words = pattern.splitAsStream("Hello World");
  1. Random 类:Stream 可以通过 Random 类的 ints()longs()doubles() 方法来生成随机数的 Stream。
Random random = new Random();
IntStream randomInts = random.ints(5, 1, 10);
  1. StreamSupport 类:Stream 可以通过 StreamSupport 类的 stream() 方法来创建自定义的 Stream。
Iterable<String> iterable = Arrays.asList("Alice", "Bob", "Carol");
Stream<String> stream = StreamSupport.stream(iterable.spliterator(), false);

这些类提供了不同的方式来创建和处理 Stream,可以根据具体的需求选择合适的类。配合不同的类使用 Stream 可以实现丰富的功能和灵活的操作。

参考

  • 官方文档

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

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

相关文章

使用T-SQL语句操作数据表-删除数据

1.使用 delete 语句删除表中的数据&#xff1a;语法&#xff1a;delete from <表名> [where <删除条件>]delete 是删除的意思 where是选填内容可以不加&#xff0c;但是不加条件的话是删除整个表 例子&#xff1a;delete from 成绩表 where 姓名张三含义&#xff1…

Oracle expdp/impdp导出导入命令及数据库备份

经常报错&#xff1a; ORA-39002: invalid operation ORA-39070: Unable to open the log file. ORA-29283: invalid file operation ORA-06512: at "SYS.UTL_FILE", line 536 ORA-29283: invalid file operation 解决方法&#xff1a; 1、 CREATE OR REPLACE DI…

exfat单元分配要设置多少_微软宣布,支持往Linux内核里添加exFAT存储了!跨系统存储的福音...

栗子 发自 凹非寺 量子位 报道 | 公众号 QbitAIexFAT&#xff0c;是微软开发的文件系统&#xff0c;为闪存而生。你的U盘、SD卡、手机等等存储设备&#xff0c;能存4G以上的大文件&#xff0c;很大程度上是它的功劳。可exFAT一直是专有的&#xff0c;微软手握多项专利。所以&am…

在linux中安装oracle中文包,在Linux命令行下安装Oracle 10g

Oracle 10g支持在命令行下用静默模式(Silent)安装&#xff0c;给那些没有安装图形界面的Linux系统提供了极大的便利。下面以Fedora Core 6为例&#xff0c;介绍在命令行下安装OracleOracle 10g的方法。1 安装前的准备准备工作要用登录为root用户来进行。1.1 选择安装环境的语言…

Jetbrains 系 IDE 编辑器的代码提示功能

著名的 Jetbrains 可谓编程界的一大福音&#xff0c;众多有名代码编辑器比如 ItelliJ IDEA、PHPStorm、WebStorm、PyCharm 等&#xff0c;均出自这家公司麾下。 对于中国的Java开发者来说&#xff0c;可能使用 Eclipse 的人最多。 使用Idea的程序员也不少, 而且每个人都在鼓吹其…

Oracle下的Databse,Instance,Schemas

1、DATABASE&#xff0c;对oracle而言&#xff0c;是指物理上的数据库&#xff0c;一般你安装了一个oracle的数据库软件后&#xff0c;就是一个database。 2、instance&#xff0c;在同一个数据库上&#xff0c;可以建立多个实例&#xff0c;这些实例互相不干扰&#xff0c;每个…

oracle实验数据库和表,1oracle创建数据库和表.doc

1oracle创建数据库和表.doc实验一&#xff1a;创建数据库和表一、实验目的1. 掌握使用DBCA创建数据库2. 掌握手工创建Oracle数据库的方法3. 掌握创建数据表的方法二、实验内容及步骤1. 使用DBCA创建数据库(1) 打开DBCA组件,创建数据库sale.(2) 安装完后进入D:\oracle\product\1…

tkmybatis 子查询_真假童子命符箓道长教你如何查询

童子命查询方法一&#xff1a;童子命在相术里&#xff0c;指的是一生都霉运连连如过本命年的人。古代关于真童子命查询有口诀“春秋甲寅子&#xff0c;冬夏卯未辰&#xff1b; 金木乙卯未&#xff0c;水火庚辛壬&#xff1b; 土命逢辰巳&#xff0c;童子定为真”解释上面的口诀…

使用 nvm 安装 nodejs 和 npm

使用 nvm 可以方便的进行 nodejs 的安装和版本管理。其实最开始使用的是 n 命令&#xff0c;命令简洁到极致了&#xff0c;无奈总是安装不成功&#xff0c;往往下载一部分就报 curl 错误。然后又找到这个 nvm&#xff0c;配合淘宝源&#xff0c;简单快捷&#xff5e; 1.到 nvm …

ECLIPSE配置OSGI服务器

eclipse版本如下&#xff1a; Eclipse Java EE IDE for Web Developers. Version: Mars Release (4.5.0) Build id: 20150621-1200 ------------------------ 1、进入eclipse-----run----run configuration---osgi framework---new 2、取消全选 3、在搜索框中输入 osgi&a…

oracle ebs r12财务月结基础讲座20090823,095921_OracleEBSR12财务月结基础讲座20090823课件.ppt...

095921_OracleEBSR12财务月结基础讲座20090823课件2009年8月23日方亚兵、巩学伟;1、月结概述 1.1)月结与对帐 1.2)子模块与总帐之间的关系 1.3)关帐顺序2、各模块详细结帐流程及对帐 2.1)应付 2.2)采购 2.3)库存 2.4)应收 2.5)资产 2.6)PAC 2.7)总帐3、应收模块业务规则介绍4、…

AD19 add pins to nets错误_为什么我认为Rust的Result错误处理方式不如Exception

由于是对技术的个人评判&#xff0c;欢迎理性讨论。我曾经也当过纯函数式的脑残粉&#xff0c;认为宇宙第一棒的代数数据结构用来处理错误&#xff0c;是无上的优雅和绝对的安全。一个看似人畜无害的接口抛出异常带来的崩溃&#xff0c;是各类疑难杂症的罪魁祸首。综合起来&…

Java @Transient 注解使用

2019独角兽企业重金招聘Python工程师标准>>> 我们建实体类的时候啊&#xff0c;有时候实体类的属性和数据库表字段不一致的时候&#xff0c;比如多一个属性&#xff0c;那你不加这个注解就会报错&#xff0c;因为映射的时候会提示&#xff08;提示啥我给忘了&#x…

Myeclipse/eclipse 安装查看class文件的插件

从http://www.oschina.net/project/tag/317/decompiler?lang19&os0&sortview 中下载了 也可到我的网盘&#xff1a;http://pan.baidu.com/s/1eS5BMcM 下载 Java反编译工具jad &#xff08;jad.exe&#xff09;和 Java反编译插件 Jadclipse &#xff08;net.sf.jadcl…

oracle—ebs_采购功能点操作手册,oracle—EBS_采购功能点操作手册

erp实施企业采购模块构架及日常业务操作指导“人力资源”页签可以设置是否“使用审批层次结构”来决定采购单据的审批路径。如不选定&#xff0c;则表示采购单据将使用员工的“主管”结构来进行审批。“员工编号”方法默认自业务组定义时的“员工编号生成”方法设置。1.2采购选…

Https的前世今生

1、年前会议 马上要过年了&#xff0c;公司业务上的需求也少了很多&#xff0c;这不&#xff0c;王小二他们召开了一场技术会议&#xff0c;盘点年前能干点啥。 只见C哥写了一份清单&#xff0c;其中一项是全站升级https。 C哥说&#xff1a;https是一种趋势&#xff0c;但目前…

combobox控件 如何把三角形放大_初中数学|全等三角形全部知识点总结

今天&#xff0c;琦老师为大家整理了[初中数学重要考点&#xff0c;全等三角形的全部知识点]&#xff0c;希望帮助大家中考数学快速提分( #小学数学#初中数学#数学)除了图片内容&#xff0c;大米君也为大家分享[如何灵活运用这些知识点的方法]大家记得跟着做起来哦~提高复习效果…

Spring中引入其他配置文件

原文&#xff1a;http://www.cnblogs.com/LiuChunfu/p/5605473.html ------------------------------------------------------------------------------ 一、引入其他 模块XML   在Spring的配置文件&#xff0c;有时候为了分模块的更加清晰的进行相关实体类的配置。 比如…

oracle不要重复记录,Oracle中去重复记录 不用distinct

用distinct关键字只能过滤查询字段中所有记录相同的(记录集相同)&#xff0c;而如果要指定一个字段却没有效果&#xff0c;另外distinct关键字会排序&#xff0c;效率很低 。select distinct name from t1 能消除重复记录&#xff0c;但只能取一个字段&#xff0c;现在要同时取…

miui游戏驱动程序偏好设置_米粉必看:小米官方教你如何关闭 MIUI 广告 - 小米,MIUI...

IT之家 11 月 9 日消息 小米的 MIUI 在用户心中的口碑一直是比较好的&#xff0c;但该系统也并非完美&#xff0c;被吐槽的较多的一个点就是系统内的广告比较多。今天&#xff0c;小米官方微博 小米服务那些事 分享了几个能够减少 MIUI 广告的方法&#xff0c;米粉不妨了解一下…