Java的Lambda表达式和Stream流的作用以及示例
Lambda介绍
- java8新特性
- Lambda表达式是一个匿名函数,有以下特性:
- a. 通过使用Lambda表达式使代码简洁、紧凑
- b. 匿名函数可以作为参数、返回值。
Lambda语法格式
(parameters)->{statements;}
parameters:参数列表。
- statements:执行语句。
->:使用指定参数完成某个功能。 - (parameters)->expression
parameters:参数列表。
expression:表达式。
->:使用指定参数完成某个功能。
使用细节
- 可选的大括号:函数体只包含一个语句,不需要大括号。
(String msg) -> System.out.println(msg);
- 可选的参数圆括号:只有一个参数,省略圆括号及参数类型。
(msg) -> System.out.println(msg);
- 可选的返回关键字return:函数体只有一个表达式,且运算结果匹配返回类型,省略return。
(int a,int b) -> a+b
- 可选的参数类型:不需要参数类型,编译器可以根据参数值进行推断。
(a,b)-> a+b
Lambda方法引用
当Lambda表达式所要完成的业务逻辑已经存在,直接引用对应的方法。 被引用的方法与函数式抽象方法:参数列表要相同、返回值类型兼容。
语法格式
通过双冒号:: 进行方法引用
哪些方法可以引用
- 静态方法 通过 类名::方法 引用,如示例,Test::run 会引用到Test类的run(),且与Runnable接口中的run方法参数、返回值相同。
public class Test { public static void main(String[] args) { new Thread(Test::run).start(); } private static void run() { System.out.println("执行业务"); } }
- 构造方法 声明User类
public class User { public User(){} }
声明函数接口
@FunctionalInterface public interface HelloLambda { public User get(); }
通过 类名::new 引用
public class Test { public static User get(HelloLambda helloLambda) { return helloLambda.get(); } public static void main(String[] args) { User user = get(User::new); } }
- 实例方法 声明函数接口
@FunctionalInterface public interface HelloLambda { public void print(String text); }
通过 对象::方法 引用
public class Test { public static void print(HelloLambda helloLambda) { helloLambda.print("HELLO"); } public static void main(String[] args) { LowerPrint test = new LowerPrint(); print(test::toLowerCase); } } class LowerPrint { public void toLowerCase(String text) { System.out.println(text.toLowerCase()); } }
Lambda使用前提
Lambda表达式的语法是非常简洁的,通过以上的示例可以发现,在使用Lambda表达式时需要满足以下条件:
- 方法的参数和局部变量类型必须为接口才能使用Lambda。
- 必须有一个函数式接口:有且只有一个抽象方法的接口
@FunctionalInterface
注解。
常见的函数式接口:
Runnable/Callable
Supplier/Consumer
Comparator
Predicate
Function
Lambda本质
Lambda本质其实就是为了解决匿名内部类使用时繁琐的代码。 举个例子:当我们启动一个线程执行任务时,需要执行以下操作
- Thread类需要一个Runnable接口作为参数,其中run方法执行核心内容。
- 为了指定run方法体,不得不需要一个Runnable的实现类。
- 为了省去定义一个Runnable的实现类,不得不使用匿名内部类。
- 使用匿名内部类时必须覆盖run方法体。
- 但是实际上我们只需要编写run方法体的内容,所以当我们使用Lambda表达式启动一个线程执行任务时,不用定义Runnable的实现类也可以不使用匿名内部类。如下示例:
new Thread(() -> System.out.println("执行业务")).start();
Lambda和匿名内部类对比
- 所需类型不一样:匿名内部类的类型可以是类、抽象类、接口;Lambda表达式所需要的类型必须是接口。
- 抽象方法的数量不一样:匿名内部类中的抽象方法数量是随意的;Lambda表达式所需要的接口中只能有一个抽象方法。
- 实现原理不一样:匿名内部类是编译后形成一个class;Lambda表达式是在程序运行时动态生成class。
Stream流介绍
Stream流的目的是增强容器的操作:List、Set、Queue等。其特点为:
- 专注于对容器对象的聚合操作
- 提供串行/并行两种模式
- 提高编程效率、可读性
Stream流使用分为3个步骤:获取流->中间操作->终结操作。
获取流
Stream<String> stringStream = Stream.of(new String[]{"a", "b"}); Stream<String> stream = new ArrayList<String>().stream();
中间操作:打开流->操作流->返回新流->交给下一个流使用。具体的操作有:map、filter、sorted、limit、skip、concat、paraller。
Stream<String> stringStream = Stream.of(new String[]{"a", "b"}); stringStream.filter(s -> s.equalsIgnoreCase("a"));
终结操作:只能有一个,最后的操作。具体的操作有:forEach、collect、min、max、count
Stream<String> stringStream = Stream.of(new String[]{"a", "b"}); stringStream.forEach(System.out::println);
到此这篇关于Java的Lambda表达式和Stream流简单示例的文章就介绍到这了,更多相关Lambda表达式和Stream流示例内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
如何利用Retrofit+RxJava实现网络请求的异常处理
这篇文章主要介绍了如何利用Retrofit+RxJava实现网络请求的异常处理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2019-04-04IntelliJ IDEA中如何构建Spring Boot的项目
这篇文章主要介绍了IntelliJ IDEA中如何构建Spring Boot的项目问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2023-07-07Java BigDecimal详解_动力节点Java学院整理
BigDecimal 由任意精度的整数非标度值 和32 位的整数标度 (scale) 组成。接下来通过本文给大家介绍Java BigDecimal详解,需要的的朋友参考下吧2017-04-04
最新评论