java8(1)lambda表达式
来源:互联网 发布:什么是云计算和云服务 编辑:程序博客网 时间:2024/06/06 00:49
1.为什么java会提供lambda表达式
忽视注解,泛型等特性,Java自诞生之初的变化并不大。在Java的世界里,函数无法独立存在。而在Javascript等函数式变成语言中,函数是一等公民,可独立存在,可被赋值给变量,或作为参数传递给其他函数。函数式编程语言提供了一种强大的功能-闭包,相比传统的编程方法,闭包有很多优势。闭包是可调用的对象,他记录一些信息,这些信息来自创建他的作用域。lambda表达式,便是Java提供的,最接近闭包概念的东西。他们之间虽然有差别,但是lambda表达式是闭包的很好替代。
http://steve-yegge.blogspot.sg/2006/03/execution-in-kingdom-of-nouns.html这篇文章里风趣幽默的解释了Java为什么要进入lamda表达式。https://dzone.com/articles/why-we-need-Lambda-expressions 这篇文章也给出了Java需要lambda表达式的解释。lambda表达式为Java添加了缺失的函数式编程的特点。但在Java中,lambda表达式是对象,他必须依附于一类特比的对象类型-函数式接口。而不像函数式编程语言中,lambda表达式的类型是函数。这是两者的区别。
2.labmda表达式的语法及常见例子
Java中lambda表达式通常使用(argument)->(body)语法。例如:
()->body;
(arg1,arg2...)->{body}
(type1 arg1,type2 arg2 ....)->{body}
以下是一些常见例子:
(int a,int b)->{return a+b;}
()->System.out.printlb("Hello world!");
()->42
()->{return 3.1415926};对其格式总结如下:
- 一个 Lambda 表达式可以有零个或多个参数
- 参数的类型既可以明确声明,也可以根据上下文来推断。例如:
(int a)
与(a)
效果相同 - 所有参数需包含在圆括号内,参数之间用逗号相隔。例如:
(a, b)
或(int a, int b)
或(String a, int b, float c)
- 空圆括号代表参数集为空。例如:
() -> 42
- 当只有一个参数,且其类型可推导时,圆括号()可省略。例如:
a -> return a*a
- Lambda 表达式的主体可包含零条或多条语句
- 如果 Lambda 表达式的主体只有一条语句,花括号{}可省略。匿名函数的返回类型与该主体表达式一致
- 如果 Lambda 表达式的主体包含一条以上语句,则表达式必须包含在花括号{}中(形成代码块)。匿名函数的返回类型与代码块的返回类型一致,若没有返回则为空
3.函数式接口
在Java中,Marker(标记)类型的接口是一种没有方法或属性声明的接口,简单的说,即为空接口。类似地,函数式接口是只包含一个抽象方法声明的接口。Java.lang.Runnalbe就是一种函数式接口,其只声明了一个方法,void run().ActionListener也是函数式接口,我们使用匿名内部类来实例化函数式接口的对象。现在,可以直接使用lambda表达式。每个lambda表达式都能隐式的赋值给函数式接口,例如,
Runnable r = () -> System.out.println("hello world");直接创建了一个runable接口的引用。当不指明函数式接口时,编译器会自动解释这种转化:
new Thread(() -> System.out.println("hello world")).start();
因此,在上面的代码中,编译器会自动推断:根据线程类的构造函数签名 public Thread(Runnable r) { },将该 Lambda 表达式赋给 Runnable 接口。
Consumer<Integer> c = (int x) -> { System.out.println(x) };
BiConsumer<Integer, String> b = (Integer x, String y) -> System.out.println(x + " : " + y);
Predicate<String> p = (String s) -> { s == null };
4.@FunctionalInterface
@FunctionalInterface 是 Java 8 新加入的一个注解,用于指明该接口类型声明是根据 Java 语言规范定义的函数式接口。Java 8 还声明了一些 Lambda 表达式可以使用的函数式接口,当你注释的接口不是有效的函数式接口时,可以使用 @FunctionalInterface 解决编译层面的错误。
以下是一种自定义的函数式接口:
@FunctionalInterface public interface WorkerInterface {
public void doSomeWork();}根据定义,函数式接口只能有一个抽象方法,如果你尝试添加第二个抽象方法,将抛出编译时错误。例如:
@FunctionalInterface
public interface WorkerInterface {
public void doSomeWork();
public void doSomeMoreWork();}
错误:
Unexpected @FunctionalInterface annotation
@FunctionalInterface ^ WorkerInterface is not a functional interface multiple
non-overriding abstract methods found in interface WorkerInterface 1 error
函数式接口定义好后,我们可以将其作为函数参数,并通过lambda表达式赋值给该参数。
@FunctionalInterfacepublic interface WorkerInterface { public void doSomeWork();//名字可以任意。调用时,会自动传话为lambda表达式的实现}public class WorkerInterfaceTest {public static void execute(WorkerInterface worker) { worker.doSomeWork();}public static void main(String [] args) { //方法一。通过匿名内部类方式实现。此时,必须显示声明实现WorkerInterface的doSomeWork方法。 execute(new WorkerInterface() { @Override public void doSomeWork() { System.out.println("Worker invoked using Anonymous class"); } }); //方法二。通过lambda表达式实现。只要是无输入参数,且返回void的,都可以赋值给WorkerInterface类型,其中并没有使用doSomeWork,他仅仅是一个函数名 execute(() -> System.out.println("Worker invoked using Lambda expression") );}}以上调用输出:
Worker invoked using Anonymous class
Worker invoked using Lambda expression
5.lambda表达式举例:
a.线程初始化
//旧方法:new Thread(new Runnable() {@Overridepublic void run() { System.out.println("Hello from thread");}}).start();//新方法:new Thread(() -> System.out.println("Hello from thread")).start();
b.打印数据所有元素:
//Old way:List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);for(Integer n: list) { System.out.println(n);}//New way:List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);list.forEach(n -> System.out.println(n));//or we can use :: double colon operator in Java 8list.forEach(System.out::println);使用 Java 8 全新的双冒号(::)操作符将一个常规方法转化为 Lambda 表达式
c。计算数据每个元素平方后的总和:
//Old way:List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);int sum = 0;for(Integer n : list) { int x = n * n; sum = sum + x;}System.out.println(sum);//New way:List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);int sum = list.stream().map(x -> x*x).reduce((x,y) -> x + y).get();System.out.println(sum);我们使用了 .stream() 方法将常规数组转化为流。Java 8 提供了非常cool的流 APIs。java.util.stream.Stream 接口包含许多有用的方法,能结合 Lambda 表达式产生神奇的效果。我们将 Lambda 表达式 x -> x*x 传给 map() 方法,该方法会作用于流中的所有元素。java8 stream我们将在下一篇中介绍。
使用匿名类与 Lambda 表达式的一大区别在于关键词的使用。对于匿名类,关键词 this 解读为匿名类,而对于 Lambda 表达式,关键词 this 解读为写就 Lambda 的外部类。
Lambda 表达式与匿名类的另一不同在于两者的编译方法。Java 编译器编译 Lambda 表达式并将他们转化为类里面的私有函数,它使用 Java 7 中新加的 invokedynamic 指令动态绑定该方法,具体可阅读文章:http://blog.takipi.com/compiling-Lambda-expressions-scala-vs-java-8/
- java8(1)lambda表达式
- java8 lambda表达式 (1)
- ()-> java8:Lambda表达式
- Java8 turial - Lambda 表达式(1)
- Java8新特性之Lambda表达式(1)
- java8之Lambda表达式 1:简介
- java8之Lambda表达式 1:简介
- java8新增特性(一)---Lambda表达式
- Java8体验(一)lambda表达式语法
- JAVA8新特性(Lambda 表达式)
- java8新特性(二):Lambda表达式
- java8新特性(拉姆达表达式lambda)
- Java8新特性(拉姆达表达式lambda)
- java8 笔记-Lambda表达式(一)
- JAVA8新特性(Lambda表达式)
- (二)Java8之Lambda表达式
- Java8 Lambda表达式教程
- Java8 Lambda表达式教程
- 构建链表、输出链表元素、删除链表…
- 用队列和栈的功能实现回文的判定
- WPF学习感受
- 未声明的标识符SurfFeatureDetecto…
- Moving Tables
- java8(1)lambda表达式
- Matlab中Simulink的Bus/Mux/Dumx模块详解
- vue 引入echarts画中国地图 Map china not exists
- javascript获取地址栏参数的方法
- js中表单提交进行校验
- nodejs异常之-Error: listen EACCES 127.0.0.1:8000
- C#剪刀 石头 布
- Django Models
- 关于如何系统化学习,如何专业化学习