Java8特性Lambda表达式

Posted 浮梦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java8特性Lambda表达式相关的知识,希望对你有一定的参考价值。

Lambda 表达式

简介:

  • Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
  • Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
(parameters) -> expression
 或
 (parameters) ->{ statements; }

使用 Lambda 表达式需要注意以下两点:

  • Lambda 表达式主要用来定义行内执行的方法类型接口,例如,一个简单方法接口。在上面例子中,我们使用各种类型的Lambda表达式来定义MathOperation接口的方法。然后我们定义了sayMessage的执行。
  • Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。

变量作用域

lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误 。

我们也可以直接在 lambda 表达式中访问外层的局部变量。

final int num = 1;
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num)); s.convert(2);  // 输出结果为 3 

lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)

在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。

方法引用

  • 方法引用通过方法的名字来指向一个方法。
  • 方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
  • 方法引用使用一对冒号 :: 。

函数式接口

函数式接口

有且只有一个抽象方法的接口,称之为函数式接口。当然接口中可以有其他方法(默认,静态,私有)

@FunctionInterface注解:可以检测接口是否是函数式接口
是:编译成功, 否:编译失败

函数式接口的使用:

一般可以作为方法的参数和返回值类型

例子:
1.定义一个函数式接口MyFunctionInterface中定义一个没有返回值的方法public void method();
2.定义一个接口的实现类MyFunctionInterFaceImpl实现函数式接口
3.定义一个测试类Demo中有一个静态方法show参数是这个函数式接口,调用接口中的方法public static void show(MyFunctionInterface myface){myface.method();}
4.在main方法中调用show方法的3中方式
a.调用show方法,参数是接口,所以可以传接口的实现类
show(new MyFunctionInterfaceImpl());
b.方法参数是一个接口,所以可以传递接口的匿名内部类
show(new MyFunctionInterface(){
@override
public void method(){System.out.print(“使用匿名内部类重写接口中的抽象方法”);}
});
c.调用show方法,方法参数是一个函数式接口所以可以使用Lambda表达式
show(()->{System.out.print(“使用lambda重写接口中的抽象方法”)});

函数式编程

  1. 函数式编程:使用Lambda表达式和方法引用简化程序。
  2. Lambda表达式的延迟执行:有些场景的代码执行后,结果不一定会被使用,从而造成性能的浪费。而Lambda是延迟执行的,这正好可以作为解决方法,提升性能。
  3. 函数式接口作为方法的参数和返回值。
    存在函数式接口就可以使用Lambda表达式。即可以使用Lambda进行传参。

使用Lambda优化日志案例:

1.Lambda的特点:延迟加载 lambda使用的前提:必须存在函数式接口(定义拼接字符串的接口)  
2.使用Lambda表达式作为参数传递,仅仅是把参数传递showLogger方法中,只有满足条件,日志的等级是1级才会调用接口MessageBuilder中的方法builderMessage才会进行拼接字符串。  

常用的函数式接口(java.util.function包中)

Supplier接口

Java.util.function.Supplier<T> 接口中仅包含一个无参的方法:T get()。  
用来获取一个泛型参数指定类型的接口数据。  
由于是一个函数式接口,这就意味着对应的Lambda表达式对外提供一个符合泛型类型的对象数据.  
Supplier<T>接口被称为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据

Consumer接口

Java.util.function.Consumer<T>接口正好与Supplier接口相反,他不是生产一个数据,而是消费一个数据,其数据类型由泛型决定。  
Consumer中包含抽象方法void accept(T t),意为消费一个指定泛型的数据。
Consumer接口是一个消费型接口,泛型执行什么类型,就可以使用accept方法消费什么类型的数据

.foreach(Consumer t)

Consumer中的默认方法andThen:组合消费   练习题
如果一个方法的参数和返回值全是Consumer类型,那么就可以实现效果:  
消费的时候,首先做一个操作,然后再做一个操作,实现组合。要想实现组合,就需要两个个Lambda表达式。

Predicate接口 判断

Java.util.function.Predicate: 
Predicate接口对某种数据类型进行判断,从而得到一个boolean值结果。
Predicate接口中的抽象方法:boolean Test(T t)用来对指定类型的数据进行判断方法
结果:符合条件:返回true
      不符合条件:返回flase
默认方法:and or ! 练习题

.filter(Predicate t)

Function接口

Java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。  
抽象方法:R apply(T t) 根据T的类型参数获取R类型的结果

.map(Function<Object, Object> f)

以上是关于Java8特性Lambda表达式的主要内容,如果未能解决你的问题,请参考以下文章

Java8新特性 Lambda表达式

Java8新特性--Lambda表达式

java8新特性之——lambda表达式的使用

java8新特性之Lambda表达式入门

Java8新特性-Lambda表达式

Java8新特性-Lambda表达式