Java的Lambda表达式和Stream流的作用以及示例
作者:叫我二蛋
这篇文章主要介绍了Java的Lambda表达式和Stream流简单示例,Lambda允许把函数作为一个方法的参数,使用Lambda表达式可以写出更简洁、更灵活的代码,而其作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升,需要的朋友可以参考下
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流示例内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!