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流使用步骤
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);
- 点赞
- 收藏
- 关注作者
评论(0)