所有示例代码打包下载 : 点击打开链接

Java8新特性 : 
  1. 接口新增默认方法和静态方法
  2. Optional类
  3. Lambda表达式
  4. 方法引用
  5. Stream API - 函数式操作流元素集合
  6. Date/Time API
  7. 新API和工具
  8. Nashorn , JavaScript引擎

3. Lambda表达式

Lambda表达式 , (函数式编程 , 也称为闭包)是Java8中最大和最令人期待的语言改变 . 它允许我们将函数当成参数传递给某个方法 , 或者把代码本身当作数据处理(函数式开发者非常熟悉这些概念 , 例如js中的将function本身当作一个参数传入另一个function中) . Lambda相当于JDK8之前的匿名内部类 , 实现了更简洁而紧凑的语言结构 , 最简单的Lambda表达式可由参数 , -> 符号和语句块组成 . 例如 :

Arrays.asList(1,2,3).forEach(i -> System.out.print(i));

完整的Lambda表达式由3部分组成 : 参数列表 , 箭头符号 , 代码内容

(Type1 param1 , Type2 param2 , ...) -> {statment1;statment2;return result;}

例如 :

map.forEach((String k , String v) -> {System.out.println(k + " , " + v);
});
Lambda的特征 :

Lambda有以下重要特征 , 这些特征可以在写法上使Lambda写法更精简
    1 . 可选类型声明 , 不需要声明参数类型 , 编译器可以统一识别参数值 . 绝大多数情况 , 编译器都可以从上下文环境中推断出Lambda表达式的参数类型 , 所以参数类型可以省略

(param1 , param2 , ...) -> {statment1;statment2;return result;}

2 . 可选的参数圆括号 , 如果只有一个参数无需定义圆括号 , 多个参数必须定义 .

param1 -> {statment1;statment2;return result;}

3. 可选的大括号 , 如果主体仅有一行语句 , 就不需要大括号和行尾分号

param1 -> statment1

4 . 可选的返回关键字 , 如果主体只有一个表达式返回值 , 则编译器会自动返回值 , 可以省略return关键字 , 但此时花括号是必须的 , 以表明表达式返回一个值(经实测 , 此时花括号也可以省略 , 新版更新了?)

param1 -> {result}

注 : 在某些情况下 , 参数和符号也可省略

Arrays.asList(1 ,2).forEach(i -> System.out.println(i)); ===> Arrays.asList(1 ,2).forEach(System.out::println);
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) ); ===> Arrays.asList( "a", "b", "d" ).sort(String::compareTo);

在实际中使用Lambda表达式时 , 需要注意以下问题 : 
    1 . 在Lambda表达式中使用外部变量时 , 该变量必须是final型的(等同于之前的匿名内部类 , 只能使用外部类final修饰的变量) , 但在Java8中 , 你没必要显式的声明为变量加上final修饰符 , 编译器则默认你使用的变量为final的

2 . Lambda和内部类的区别 : 除了精简代码外 , Lambda中如果引用this , 那么this指针是包装类 , 即Lambda被调用的类 ; 而内部类中 , 则是指内部类 .

Q : 为什么外部变量必须有final的限制 ?

1 . 实例变量和局部变量背后的实现有一个关键不同。实例变量都存储在堆中,而局部变量则保存在栈上。如果Lambda可以直接访问局部变量,而且Lambda是在一个线程中使用的,则使用Lambda的线程,可能会在分配该变量的线程将这个变量收回之后,去访问该变量。因此, Java在访问自由局部变量时,实际上是在访问它的副本,而不是访问原始变量。如果局部变量仅仅赋值一次那就没有什么区别了——因此就有了这个限制。
    2 . 这一限制不鼓励你使用改变外部变量的典型命令式编程模式

函数式接口

为了更友好方便的使用Lambda表达式 , JDK设计了函数式接口 . 函数式接口就是一个只有一个抽象方法的普通接口(除了唯一的抽象方法 , 可以有其他方法) , 它可以被隐式的转换为Lambda表达式 .

java.lang.Runnable和java.util.concurrent.Callable是函数式接口的典型表现 . 在实际过程中 , 函数式接口是容易出错的 : 如果某个人在接口定义中增加了另一个方法 , 这时 , 这个接口就不再是函数式的了 , 并且编译过程也会失败 . 为了客服函数式接口的这种脆弱性并且显式说明某个接口是函数式接口 , Java8提供了一个特殊的注解@FunctionalInterface , 将它标注在接口定义上面 , 可以在编译阶段校验 . 如果接口定义了第二个抽象方法就会编译失败 . 该注解不是必须的(但强烈建议使用中加上该注解 , Java8库中的所有相关接口都已经带有这个注解了)

比较常见的接口类 :
类名 方法 作用
Consumer<T> void accept(T t); 处理对应的参数 , 无返回
Function<T , R> R apply(T t); 处理参数t , 返回结果R
Predicate<T> boolean test(T t); 根据参数t判断真假
Supplier<T> T get(); 拿到对应的结果
BiFunction<T , U , R> R apply(T t , U u); 根据参数t , u , 得到结果R

这些函数式接口在使用Lambda表达式时作为返回类型 , JDK定义了很多现在的函数式接口 , 实际自己也可以定义接口去作为表达式的返回 , 只是大多数情况下JDK定义的直接拿来用就可以了 . 而且这些接口在JDK8集合类使用操作流时被大量使用 .

代码Demo :
package com.xbz.java8.lambda;
​
/** 函数式接口 */
@FunctionalInterface
public interface FunctionalInterface1 {
​void test();//有且仅有一个抽象方法
​//默认方法和静态方法均不影响函数式接口default void defaultMethod(){System.out.println("FuncationalInterface1.defaultMethod");}
​static void staticMethod(){System.out.println("FuncationalInterface1.staticMethod");}
}
package com.xbz.java8.lambda;
​
public class FunctionalInterfaceDemo {public static void main(String[] args){FunctionalInterfaceDemo demo1 = new FunctionalInterfaceDemo();
​demo1.hello(new FunctionalInterface1() {//匿名内部类方式调用函数式接口@Overridepublic void test() {System.out.println("Hello Lambda");}});
​demo1.hello(() -> System.out.println("Hello Lambda"));//Lambda方式调用函数式接口}
​/** 定义调用接口的方法 */public void hello(FunctionalInterface1 funcationalInterface1){funcationalInterface1.test();}
}

更详细的函数式接口文档 , 详见 http://www.runoob.com/java/java8-functional-interfaces.html

Java8新特性总结 - 3. Lambda表达式相关推荐

  1. Java8新特性1:lambda表达式入门--由浅入深,从单发步枪迈向自动步枪

    本文主要参照<java8 in action>书中对lambda的讲解,来循序渐进的引入lambda表达式,了解我们为什么,以及怎么样初步学会使用lambda表达式,看完以后你会恍然大悟, ...

  2. JDK8新特性(一)之Lambda表达式

    Java8发布于2014年03月18日,是目前企业中使用最广泛的一个版本.Java8是一次重大的版本升级,带来了很多的新特性: 1.Lambda表达式 2.接口的增强 3.常用的内置函数式接口 4.方 ...

  3. JDK8新特性简介、Lambda表达式、Stream流常用api介绍

    JDK8新特性简介.Lambda表达式.Stream流常用api介绍 接口 Java1.8前接口中是不允许有普通方法的,在Java1.8后允许接口中有普通方法,只需要加上default关键字即可: J ...

  4. java8 lambda 接口_Java8新特性之一:Lambda表达式

    Java8是自java5之后最重大的一次更新,它给JAVA语言带来了很多新的特性(包括编译器.类库.工具类.JVM等),其中最重要的升级是它给我们带来了Lambda表达式和Stream API. 1. ...

  5. 学习笔记之-java8的新特性-函数式接口,lambda表达式,方法引用,Stream API,Optional类

    1.Lambda表达式 用匿名内部类的方法去创建多线程1.new Thread2.参数传递new Runnable3.重写run方法4.在run方法中去设置线程任务5.调用start问题:我们最终目标 ...

  6. java8新特性(拉姆达表达式lambda)

    一.函数式接口 函数式接口(functional interface 也叫功能性接口,其实是同一个东西).简单来说,函数式接口是只包含一个方法的接口.比如Java标准库中的java.lang.Runn ...

  7. Java8新特性系列(Lambda)

    上期我们分析了Java8中Interface的相关新特性,其中包括函数式接口,可以在调用时,使用一个Lambda表达式作为参数,那么我们就来谈谈Java8中的Lambda表达式吧. 定义 Lambda ...

  8. foreach lambda写法_Java8新特性之forEach+Lambda 表达式遍历Map和List

    这是Java8系列的第二篇,今天来说一下Java8中forEach的简单使用.我们使用对比的方式来看应该会看得更加清楚,更能理解: 一.遍历Map ============Java8之前的方式==== ...

  9. .net framework3.5新特性1:Lambda表达式

    本文介绍了.net 3.5 framework中的Lambda表达式.这种表达式可以取代delegate,作为方法指针来使用.     在C#2.0及C#1.x中,需要使用delegate来定义方法指 ...

最新文章

  1. docker安装mysql5.7_超详细Docker安装Mysql5.7并进行挂载
  2. 【超详细】手把手教你使用YOLOX进行物体检测(附数据集)
  3. 算法----删除链表中的节点(Java)
  4. 四、pink老师的学习笔记——元素的显示与隐藏
  5. php如何复制一个对象,PHP中的对象复制及__clone() 函数
  6. ajax 请求成功 再执行javascript,jquery中ajax请求后台数据成功后既不执行success也不执行error的完美解决方法...
  7. 文件,多级目录的拷贝 笔记学习
  8. linux中删除文件名称乱码
  9. echart3 click点击事件使用
  10. corrplot包与ggcorrplot相关图(二)
  11. Butterworth滤波
  12. 计算机右键管理删除,【win7右键菜单管理】右键菜单的设置及清除
  13. 前端web要学mysql吗_学前端必须学习HTML和js吗?
  14. 2019年最新个人所得税计算器(源码/网页版/已发布)
  15. 经常手误怎么办?Delete键旁边是电源键
  16. 四十岁以后,如何做夫妻?
  17. 最佳平方逼近 matlab,matlab最佳平方逼近
  18. EduCoder-程序设计技术R-函数-(第1关:求和)(第2关:回文数计算)(第3关: 编写函数求表达式的值)(第4关:阶乘数列)(第5关:亲密数)(第6关:公约公倍数)
  19. wptx64能卸载吗_Win10如何卸载应用?Win10内置应用卸载方法
  20. 使用Excel下载数据库里的数据

热门文章

  1. WCF学习之旅—第三个示例之四(三十)
  2. 【转】Pro Android学习笔记(八):了解Content Provider(下中)
  3. 用Express搭建 blog (一)
  4. 浏览器兼容console对象的简要解决方案
  5. 每个前端工程师都应该懂的前端性能优化总结:
  6. LeetCode--5.最长回文子串(滑动窗口)
  7. 入门机器学习(六)--课后作业解析-logistics回归(python实现)
  8. R7-11 h0096. 单词合并 (10 分)
  9. 7-65 藏头诗 (15 分)
  10. 力扣20-有效的括号(C++,附思路)