一、lambda表达式的来源

Lambda 表达式(拉姆达表达式)来源于lambda演算是Alonzo Church给出的一套图灵机等价的形式计算系统。lambda演算系统以函数和变量为基础,也可以进行符号演算。Church希望用这套系统来表示有关数学的一切,比如说,用一系列函数来表达自然数。
“Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式树类型。lambda表达式是匿名函数,但是匿名函数不全是使用lambda表达式来写的。

二、编程语言中的lambda表达式和匿名函数
C#有lambda、匿名函数,js有匿名函数、闭包(Ruby之父松本行弘在《代码的未来》一书中解释:闭包就是把函数以及变量包起来,使得变量的生存周期延长),OC中有block,从功能性上说lambda和closure(或是OC中的blocks)是一个东西,只是不同语言的不同称呼罢了,它们都是匿名函数。若匿名函数捕获了一个外部变量,那么它就是一个closure。使用它们一般会有两个好处:简洁、捕获变量.
1.简洁
比如一个方法只在这一处使用,我们就没有必要创建方法然后调用,我们可以直接在其他函数内部声明定义,这样将来查找也不用去其他地方查找了也是比较方便的。例如OC中页面传值一般用代理或block,代理的话每次都要设置delagate,实现代理方法,创建的对象和代理方法分离,这样以后维护某个功能,就可能会忘记实现代理。
2.捕获变量
捕获变量在js中更能说明了。由于js中的作用域和其他语言的不一样.闭包其实就是函数的嵌套,内层的函数可以使用外层函数的所有变量,即使外层函数已经执行完毕。使用闭包减少对全局变量是使用.

三、Java中中的lambda表达式

由于Java是相对较为面向对象的语言,一个Java对象中可以包含属性和方法(函数),方法(函数)不能孤立于对象单独存在。这样就产生了一个问题,有时候需要把一个方法(函数)作为参数传到另外一个方法中的时候(比如回调功能),就需要创建一个包含这个方法的接口,传递的时候传递这个接口的实现类,一般是用匿名内部类的方式来。如下面代码,首先创建一个Runnable的接口,在构造Thread时,创建一个Runnable的匿名内部类作为参数:

Java代码 

等同于

Java代码 
  1. ;}

继续看更多的例子:

Java代码 
  1. (String s) -> { System.out.println(s); }

创建一个FileFilter,文件过滤器:

Java代码 
  1. FileFilter java = (File f) -> f.getName().endsWith(".java")

创建一个线程:

Java代码 
  1. new Thread(() -> {
  2. //do sth here...
  3. }).start()

创建一个Callable:

Java代码 
  1. Callable<String> c = () -> "done";

创建一个String的比较器:

Java代码 
  1. Comparator<String> c = (s1, s2) -> s1.compareToIgnoreCase(s2);

而且lambda表达式可以赋值给一个变量:

Java代码 
  1. Comparator<String> c;
  2. c = (String s1, String s2) -> s1.compareToIgnoreCase(s2);

还可以作为方法的返回值:

Java代码 
  1. public Runnable toDoLater() {
  2. return () -> {
  3. System.out.println("later");
  4. };
  5. }

从上面可以看到,一个lambda表达式被作为一个接口类型对待,具体对应哪个接口,编译器会根据上下文环境推断出来,如下面的lambda表达式就表示一个ActionListener.

Java代码 
  1. ActionListener l = (ActionEvent e) -> ui.dazzle(e.getModifiers());

这有可能会造成一个表达式在不同的上下文中被作为不同的类型,如下面的这种情况,尽管两个表达式是相同的,上面的表达式被推断为Callable的类型,下面的会被推断为PrivilegedAction类型。

Java代码 
  1. Callable<String> c = () -> "done";
  2. PrivilegedAction<String> a = () -> "done";

那么编译器是根据哪些因为决定一个表达式的类型呢?

如果一个表达式被推断为是T类型的,需要满足以下4个条件:

1.T是函数式接口类型(只声明唯一一个方法)

2.表达式和T中声明的方法的参数个数一致,参数类型也一致

3.表达式和T中声明的方法的返回值类型一致

4.表达式和T中声明的方法抛出的异常一致

JAVA8与lambda表达式的更多相关文章

  1. Java8中Lambda表达式的10个例子

    Java8中Lambda表达式的10个例子 例1 用Lambda表达式实现Runnable接口 //Before Java 8: new Thread(new Runnable() { @Overri ...

  2. java8的lambda表达式,将List<DTO> 转为 List<DO>

    将List<PhoneDTO>转为List<PhoneDO>,通过java8的lambda表达式来操作,比传统的for循环精简很多: /** * List<PhoneDT ...

  3. java8的lambda表达式

    关于java8的lambda表达式 lambda表达式一般用于接口,因为lambda表达式是函数式编程. 1.有且仅有一个抽象方法被称为函数式接口,函数式接口可以显示的被@FunctionalInte ...

  4. java8中lambda表达式的应用,以及一些泛型相关

    语法部分就不写了,我们直接抛出一个实际问题,看看java8的这些新特性究竟能给我们带来哪些便利 顺带用到一些泛型编程,一切都是为了简化代码 场景: 一个数据类,用于记录职工信息 public clas ...

  5. java8之lambda表达式(1)-基本语法

    lambda表达式,即带有参数的表达式,为更清晰地理解lambda表达式,先看如下例子: (1) class Student{ private String name; private Double ...

  6. java8之lambda表达式入门

    1.基本介绍 lambda表达式,即带有参数的表达式,为了更清晰地理解lambda表达式,先上代码: 1.1 两种方式的对比 1.1.1 方式1-匿名内部类 class Student{ privat ...

  7. JAVA8之lambda表达式具体解释,及stream中的lambda使用

    前言: 本人也是学习lambda不久,可能有些地方描写叙述有误,还请大家谅解及指正! lambda表达式具体解释 一.问题 1.什么是lambda表达式? 2.lambda表达式用来干什么的? 3.l ...

  8. 十分钟学会Java8的lambda表达式和Stream API

    01:前言一直在用JDK8 ,却从未用过Stream,为了对数组或集合进行一些排序.过滤或数据处理,只会写for循环或者foreach,这就是我曾经的一个写照. 刚开始写写是打基础,但写的多了,各种乏 ...

  9. java8中Lambda表达式和Stream API

    一.Lambda表达式 1.语法格式 Lambda是匿名函数,可以传递代码.使用“->”操作符,改操作符将lambda分成两部分: 左侧:指定了 Lambda 表达式需要的所有参数 右侧:指定了 ...

  10. Java8之lambda表达式

    一.什么是lambda表达式? Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码 ...

随机推荐

  1. JS——全选与全不选

    1.每个子input标签都需要进行判断 2.使用开闭原则,一旦满足条件就改变默认值 3.在给主input标签注册事件时,要求主input标签的checked值赋值给子标签 <!DOCTYPE h ...

  2. C#的一些知識點

    不能將屬性以ref或out的方式傳遞 看上去屬性和字段差不多,可是屬性本質上是個方法,并不是真正指向一個内存位置,所以不能像字段那樣能以ref或out方式傳遞. Lookup運行一個鍵對應多個值,但無 ...

  3. 几种fullpage用法及demo

    jQuery全屏滚动插件fullPage.js https://github.com/alvarotrigo/fullPage.js http://www.dowebok.com/77.html 全屏 ...

  4. transactoin

    hibernate对数据的操作是封装在事务当中,并且默认是非自动提交方式.所以用session保存对象时,如果不开启事务,并且手工提交事务,对象并不会真正保存在数据库中.

  5. Java并发——阿里架构师是如何巧用线程池的!

    一.创建线程 1.创建普通对象,只是在JVM的堆里分配一块内存而已 2.创建线程,需要调用操作系统内核的API,然后操作系统需要为线程分配一系列资源,成本很高 线程是一个重量级对象,应该避免频繁创建和 ...

  6. 20190625_mysql5.7查看及其解锁_被锁的表

    [root@localhost ~]# mysql -u myroot -pEnter password: mysql> show OPEN TABLES where In_use > 0 ...

  7. c++ list双向链表管理对象

    #cat list.cc #include <cstdlib> #include <iostream> #include <stdio.h> using names ...

  8. 【js】数组置空的其他方式及使用场景

    数组在js中属于引用型类型. var arr = [1, 2, 3]; a = []; 通常使用以上方式.如果使用场景必须使用方法置空, 可以采用arr.length = 0; 或者使用a.splic ...

  9. 爬虫文件存储:txt文档,json文件,csv文件

    5.1 文件存储 文件存储形式可以是多种多样的,比如可以保存成 TXT 纯文本形式,也可以保存为 Json 格式.CSV 格式等,本节我们来了解下文本文件的存储方式. 5.1.1 TXT文本存储 将数 ...

  10. Python爬虫基础--分布式爬取贝壳网房屋信息(Server)

    1. server_code01 2. server_code02 3. server_code03