1.lambada的存在来由

匿名类的一个问题是,如果匿名类的实现非常简单,例如只包含一个方法的接口,那么匿名类的语法可能看起来不实用且不清楚。在这些情况下,您通常会尝试将功能作为参数传递给另一个方法,例如当有人单击按钮时应采取的操作。Lambda表达式使您可以执行此操作,将功能视为方法参数,或将代码视为数据。

单 interface 单method

public interface Predicate<T> {

    /**     * Evaluates this predicate on the given argument.     *     * @param t the input argument     * @return {@code true} if the input argument matches the predicate,     * otherwise {@code false}     */    boolean test(T t);

2.lambada理想用例

参考 java.util.function 下面的个别functionnal interfaces

Consequently, the JDK defines several standard functional interfaces, which you can find in the package java.util.function.

定义一个 Person 类

public class Person {public enum Sex {MALE, FEMALE}String name;LocalDate birthday;Sex gender;String emailAddress;public int getAge() {// ...}public void printPerson() {// ...}
}

有一个List<Person> 我们要打印出指定条件的Person信息,用lamdaba表达式实现可以这么做

方式一

public static void listConditionPerson(List<Person> person, Predicate<Person> pre, Consumer<Person> conf) {    for (Person p : person) {        if (pre.test(p))            conf.accept(p);    }}

调用方式为:  
listConditionPerson(person, person1 -> person1.getAge() > 10 && person1.getAge() <= 30, Person::printPerson);

方式二:使用泛型(generics)的模式改造一下方法,可以支持不同队形的相同功能

public static <X, Y> void processElements(Iterable<X> source,Predicate<X> tester,Function <X, Y> mapper,Consumer<Y> block) {for (X p : source) {if (tester.test(p)) {Y data = mapper.apply(p);block.accept(data);}}
}

调用方式为

 processElements(        person,        p -> p.getGender() == Person.Sex.MALE                && p.getAge() >= 18                && p.getAge() <= 25,        p -> p.getEmailAddress(),        email -> System.out.println(email));

方式三:使用支持lambada的聚合函数(stream api)

person.stream().filter(person1 -> person1.getAge() > 10).map(p ->    p.getEmailAddress()).forEach(email -> {    System.out.println(email);});

并发版
person.parallelStream().filter(person1 -> person1.getAge() > 10).map(p ->        p.getEmailAddress()).forEach(email -> {    System.out.println(email);});
lambda 语法官方介绍

bda expression looks a lot like a method declaration; you can consider lambda expressions as anonymous methods—methods without a name.

The following example, Calculator, is an example of lambda expressions that take more than one formal parameter:

public class Calculator {interface IntegerMath {int operation(int a, int b);   }public int operateBinary(int a, int b, IntegerMath op) {return op.operation(a, b);}public static void main(String... args) {Calculator myApp = new Calculator();IntegerMath addition = (a, b) -> a + b;IntegerMath subtraction = (a, b) -> a - b;System.out.println("40 + 2 = " +myApp.operateBinary(40, 2, addition));System.out.println("20 - 10 = " +myApp.operateBinary(20, 10, subtraction));    }
}

The method operateBinary performs a mathematical operation on two integer operands. The operation itself is specified by an instance of IntegerMath. The example defines two operations with lambda expressions, addition and subtraction. The example prints the following:

40 + 2 = 42
20 - 10 = 10

Accessing Local Variables of the Enclosing Scope

Like local and anonymous classes, lambda expressions can capture variables; they have the same access to local variables of the enclosing scope. However, unlike local and anonymous classes, lambda expressions do not have any shadowing issues (see Shadowing for more information). Lambda expressions are lexically scoped. This means that they do not inherit any names from a supertype or introduce a new level of scoping. Declarations in a lambda expression are interpreted just as they are in the enclosing environment. The following example, LambdaScopeTest, demonstrates this:

import java.util.function.Consumer;public class LambdaScopeTest {public int x = 0;class FirstLevel {public int x = 1;void methodInFirstLevel(int x) {// The following statement causes the compiler to generate// the error "local variables referenced from a lambda expression// must be final or effectively final" in statement A://// x = 99;Consumer<Integer> myConsumer = (y) -> {System.out.println("x = " + x); // Statement ASystem.out.println("y = " + y);System.out.println("this.x = " + this.x);System.out.println("LambdaScopeTest.this.x = " +LambdaScopeTest.this.x);};myConsumer.accept(x);}}public static void main(String... args) {LambdaScopeTest st = new LambdaScopeTest();LambdaScopeTest.FirstLevel fl = st.new FirstLevel();fl.methodInFirstLevel(23);}
}

This example generates the following output:

x = 23
y = 23
this.x = 1
LambdaScopeTest.this.x = 0

If you substitute the parameter x in place of y in the declaration of the lambda expression myConsumer, then the compiler generates an error:

Consumer<Integer> myConsumer = (x) -> {// ...
}

The compiler generates the error "variable x is already defined in method methodInFirstLevel(int)" because the lambda expression does not introduce a new level of scoping. Consequently, you can directly access fields, methods, and local variables of the enclosing scope. For example, the lambda expression directly accesses the parameter x of the method methodInFirstLevel. To access variables in the enclosing class, use the keyword this. In this example, this.x refers to the member variable FirstLevel.x.

However, like local and anonymous classes, a lambda expression can only access local variables and parameters of the enclosing block that are final or effectively final. For example, suppose that you add the following assignment statement immediately after the methodInFirstLevel definition statement:

void methodInFirstLevel(int x) {x = 99;// ...
}

Because of this assignment statement, the variable FirstLevel.x is not effectively final anymore. As a result, the Java compiler generates an error message similar to "local variables referenced from a lambda expression must be final or effectively final" where the lambda expression myConsumer tries to access the FirstLevel.x variable:

System.out.println("x = " + x);

Target Typing

How do you determine the type of a lambda expression? Recall the lambda expression that selected members who are male and between the ages 18 and 25 years:

p -> p.getGender() == Person.Sex.MALE&& p.getAge() >= 18&& p.getAge() <= 25

This lambda expression was used in the following two methods:

  • public static void printPersons(List<Person> roster, CheckPerson tester) in Approach 3: Specify Search Criteria Code in a Local Class

  • public void printPersonsWithPredicate(List<Person> roster, Predicate<Person> tester) in Approach 6: Use Standard Functional Interfaces with Lambda Expressions

When the Java runtime invokes the method printPersons, it's expecting a data type of CheckPerson, so the lambda expression is of this type. However, when the Java runtime invokes the method printPersonsWithPredicate, it's expecting a data type of Predicate<Person>, so the lambda expression is of this type. The data type that these methods expect is called the target type. To determine the type of a lambda expression, the Java compiler uses the target type of the context or situation in which the lambda expression was found. It follows that you can only use lambda expressions in situations in which the Java compiler can determine a target type:

  • Variable declarations

  • Assignments

  • Return statements

  • Array initializers

  • Method or constructor arguments

  • Lambda expression bodies

  • Conditional expressions, ?:

  • Cast expressions

Target Types and Method Arguments

For method arguments, the Java compiler determines the target type with two other language features: overload resolution and type argument inference.

Consider the following two functional interfaces ( java.lang.Runnable and java.util.concurrent.Callable<V>):

public interface Runnable {void run();
}public interface Callable<V> {V call();
}

The method Runnable.run does not return a value, whereas Callable<V>.call does.

Suppose that you have overloaded the method invoke as follows (see Defining Methods for more information about overloading methods):

void invoke(Runnable r) {r.run();
}<T> T invoke(Callable<T> c) {return c.call();
}

Which method will be invoked in the following statement?

String s = invoke(() -> "done");

The method invoke(Callable<T>) will be invoked because that method returns a value; the method invoke(Runnable) does not. In this case, the type of the lambda expression () -> "done" is Callable<T>.


博客新手,勿喷!

转载于:https://www.cnblogs.com/semonshi/p/11447494.html

lambada 表达式相关推荐

  1. 2.cocos2dx 3.2中语法的不同之处,lambada表达式的使用和function和bind函数的使用

    1        打开建好的T32  Cocos2dx-3.2的一个项目 2        设置Cocos显示窗口的位置是在AppDelegate.cpp中: 3  设置自适应窗口大小的代码是在上面的 ...

  2. lambada表达式

     lambda表达式 //C++ 11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作.Lambda的语法形式如下: //[函数对象参数](操作符重载函数参数)mutable或e ...

  3. Lambada表达式常用案例(技能题)

    一:Lambada表达式的结构 1)Lambada表达式的结构我们可以看成三部分 () -> {},箭头左边是参数,右边是执行体,箭头是格式 二:使用案例(List为主的操作) 1)实体对象 @ ...

  4. lambada表达式介绍

    前言 在其他语言中,函数式编程是很常见的,java8中为了支持函数式编程,新增了lambada表达式.lambada表达式其实是匿名内部类和闭包的一种符号表示,至于概念性的问题,大家不必深究,lamb ...

  5. JDK1.8之Lambada表达式一

    一. lambada表达式简介 我们知道对于Java变量可以赋给其一个值,而如果想将"一块代码(一个完整的方法)"赋给一个Java变量,如下所示,怎么做呢? 你可能认为就是下面的方 ...

  6. lambada表达式总结

    前言 作为jdk1.8的新特性,8的标准库都开始大量使用lambda表达式了,你有什么理由不去学习lambda,这么简洁,这么爽的一种编程方法,不学不觉得可惜吗? lambda即λ,是匿名函数的意思, ...

  7. Python(十)lambada表达式

    一.Lambda 表达式 概念:是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数. ...

  8. 第十节 Java工具包-Collections 流--lambada表达式

     collection为核心的接口,包含了多种不同类型的集合以及多种不同数据结构的实现的类 list  set queue都是在collection接口下的所以都有.add()方法 package c ...

  9. Lambada表达式的用法

    Lambada表达式是JDK1.8中最重要的新功能之一.使用Lambada表达式可以替代只有一个抽象函数的接口实现,告别匿名内部类.代码看起来更简洁易懂.Lambada表达式同时还提升了对集合.框架的 ...

  10. lambada表达式理解

    lambada表达式是替换匿名内部类的函数式接口实现类 函数式接口 只有一个抽象方法的接口(可以有默认方法和静态方法),通常带有@FunctionalInterface注解 常用函数式接口 Predi ...

最新文章

  1. 【VMCloud云平台】SCO(四)流程准备
  2. 95. 费解的开关【二级制枚举】
  3. 解决yarn报错:Found incompatible module (yarn config set ignore-engines true)
  4. 列表-列表统计及删除方法扩展
  5. OkHttp如何移除User-Agent,Accept-Encoding等框架自动添加的请求头参数
  6. Mac 系统部署Frp内网穿透服务 实现frpc shell启动脚本启动、停止
  7. numpy_basic
  8. Introduction to Mathematical Thinking - Week 4
  9. CCF201703-5 引水入城(100分题解链接)
  10. getElementById和ByTagName的区别
  11. 安装卸载gitlab
  12. 如何绘制高质量业务流程图
  13. TMDB数据导入elasticsearch7
  14. 人类的社会制度:封建制度(封建社会)
  15. php随机生成微信昵称(二)
  16. [ C语言版 ] 数独计算器 [ 搜索剪枝法 ]
  17. OpenCV物体颜色检测(Python)
  18. 初中生用计算机作弊,初中生,总是偷偷用手机作弊,好想哭怎么办?
  19. 焦作师范高等专科学校计算机,热烈欢迎丨焦作师范高等专科学院计算机与信息工程学院莅临智游...
  20. 计算机考研360能去哪里,考研360分是什么水平

热门文章

  1. Linux新加硬盘挂载
  2. Java JDK 下载官方网站
  3. 2020计算机数电实验第四次(2)
  4. 想自学编程,不知道先学哪个?
  5. CVTE笔试面试经验分享(硬件)—2020秋招
  6. OKhttp3工具类
  7. bbr是什么?有什么用?如何安装使用?
  8. Java使用AES加解密
  9. 前端的Docker入门实战
  10. python+selenium实现微博登录和自动评论