相信作为一个Java程序员都会或多或少的了解过Java8中的lambda表达式、函数式编程等,本人也是用过lambda表达式,使用的都是比较简单

的实现

通过一个例子去都感受lambda:

Comparator<Student> comparator = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getStudentAge() - o2.getStudentAge();
}
};
Comparator<Student> comparator1 = (Student o1, Student o2) -> o1.getStudentAge() - o2.getStudentAge();

一、什么是lambda表达式?

  可以理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。

1、匿名:

  我们说匿名,是因为它不像普通的方法那样有一个明确的名称:写得少而想得多!

2、函数:

  我们说它是函数,是因为Lambda函数不像方法那样属于某个特定的类。但和方法一样,Lambda有参数列表、函数主体、返回类型,还可能有可以

抛出的异常列表。

3、传递:

  Lambda表达式可以作为参数传递给方法或存储在变量中。

4、简洁:

  无需像匿名类那样写很多模板代码。

上面的定义有点长,我们主要是去理解lambda的特点。lambda这个词自于学术界开发出来的一套用来描述计算的λ演算法

二、lambda表达式结构

1、参数:采用了Comparator中compare方法的参数,两个Student。

2、箭头:箭头 -> 把参数列表与Lambda主体分隔开。

3、主体:比较两个Student的年龄。表达式就是Lambda的返回值了。

基本语法

1、(parameters) -> expression

2、(parameters) -> { statements; }  //请注意语句的花括号

举个栗子

(String s) -> s.length()
(int x, int y) -> {
System.out.println("Result:");
System.out.println(x+y);
}

第一个例子:参数为String类型并返回一个 int 。Lambda没有 return 语句,因为已经隐含了 return,对应第一种语法

第二个例子:具有两个 int 类型的参数而没有返回值( void返回)。注意Lambda表达式可以包含多行语句,对应第二种语法

错误示例:

 () -> {return "Mario";}                  //这也是正确的lambda,显式返回String
(Integer i) -> return "Alan" + i; // 错误的lambda,需要使用花括号
(String s) -> {"IronMan";} //这是一个表达式,不是一个语句,可以改成
(String s) -> "Iron Man"或者 (String s)->{return "IronMan";}

三、在哪里使用、怎么使用lambda

函数式接口

  就是有且只有一个抽象方法的接口,例如Runnable,Callable

  Lambda表达式允许以内联的形式为为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例

举个栗子

Runnable r1 = () -> System.out.println("Hello World 1");  //使用lambda表达式
Runnable r2 = new Runnable(){                  //使用匿名内部类
public void run(){
System.out.println("Hello World 2");
}
};

PS:default、static方法是不算的,照样还是函数式接口

@FunctionalInterface
public interface abc{ void add();
static void del() {
System.out.println("aaa");
};
default void update(){
System.out.println("bbb");
};
}

函数描述符

  函数式接口的抽象方法的签名基本上就是Lambda表达式的签名。我们将这种抽象方法叫作函数描述符。

例如:

  1、Runnable接口只有一个run(),而且返回值是void,所以签名就是() -> void,代表参数为空,返回值为void

  2、Callable接口只有一个call(),而且返回值是T(你可以通过String或者其他数据类型去代替),签名是 () -> String

来个反面教材

execute(() -> "abc");                        //返回值定义为String,签名() -> String,就和Runnable中的抽象方法run的签名不相匹配了
public void execute(Runnable r){
r.run();
}

  Lambda表达式可以被赋给一个变量,或传递给一个接受函数式接口作为参数的方法,当然这个Lambda表达式的签名要和函数式接口的抽象方法一样

举个栗子

public void process(Runnable r){
r.run();
}
process(() -> System.out.println("This is awesome!!"));

结果:

This is awesome!!

相当于

test.process(new Runnable() {
@Override
public void run() {
System.out.println("This is awesome!!");
}
});

@FunctionalInterface

  表示该接口会设计成一个函数式接口,如果不是函数式接口,注解就会报错,表示存在多个抽象方法,这个注解不是必须的,就像

@Override一样

很多接口在Java8中都添加了这个注解

@FunctionalInterface
public interface Comparator<T> {} @FunctionalInterface
public interface Runnable {)

简单使用总结:

  1、对于函数式接口的使用

Runnable runnable = () -> {
System.out.println("abc");
};

  2、作为函数式接口方法的参数

public void process(Runnable r){
r.run();
}
process(() -> System.out.println("This is awesome!!"));

  3、赋值给一个变量

  4、对集合的循环遍历

List<Student> list = Arrays.asList(new Student(1001, "sam", 20),
new Student(1002, "jesen", 28));
list.forEach(student -> {
System.out.println(student);
});

以上只是lambda的简单使用,可以当做入门,更进一步,结合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代码变的更加简洁

下面的例子来自:zhihu.com/question/20125256/answer/324121308

@FunctionalInterface
public interface Excutor {
void excutor(Student student);
}
@FunctionalInterface
public interface NameChecker { boolean check(Student student);
}
public static void checkAndExcutor(List<Student> studentList, NameChecker nameChecker, Excutor excutor) {
for (Student student : studentList) {
if (nameChecker.check(student)) {
excutor.excutor(student);
}
}
}

我们调用这个静态函数并赋值lambda表达式

我们一般能想到的方式

checkAndExcutor(studentList, student -> student.getStudentName().startsWith("s"),
student -> System.out.println(student.getStudentName()));

下面应该是最简洁的版本

    studentList.stream()
.filter(student -> student.getStudentName().startsWith("s"))
.forEach(System.out::println);

想要理解这些,需要了解函数式编程等各种Java8知识

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. iOS开发----iOS 8的虚化效果

    在iOS 7中,一个重大的改变就是随处可见的虚化,这在通知中心和控制中心表现得尤为抢眼: 然而,当开发人员们着手去将类似的模糊效果增加自己的App的时候,他们会发现有相当严重的障碍. 那时苹果所界定的 ...

  2. Myeclipse10集成Flex4.6

    安装好flash builder4.6 执行fb安装文件夹下utilities\Adobe Flash Builder 4.6 Plug-in Utility.exe 插件. 第一次选择flash b ...

  3. 洛谷P2668 斗地主==codevs 4610 斗地主[NOIP 2015 day1 T3]

    P2668 斗地主 326通过 2.6K提交 题目提供者洛谷OnlineJudge 标签搜索/枚举NOIp提高组2015 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 出现未知错误是说梗啊 ...

  4. 【bzoj1260】[CQOI2007]涂色paint

    题意:就是说一开始一个序列是空的,然后每次可以将连续的一段染成同一颜色,问多少次才能到目标状态. 一开始想的是二分,然后题解DP... f[i][j]表示区间[i,j]需要染色多少次 首先初始状态是f ...

  5. 实现一个简易的express中间件

    代码: // 通过闭包实现单例 const Middlewave = (function(){ let instance; class Middlewave{ constructor() { this ...

  6. P3199 [HNOI2009]最小圈 01分数规划

    裸题,第二个权值是自己点的个数.二分之后用spfa判负环就行了. 题目描述 考虑带权的有向图G=(V,E)G=(V,E)G=(V,E)以及w:E→Rw:E\rightarrow Rw:E→R,每条边e ...

  7. ubuntu 16.04 Sqoop 安装

    1.下载:https://mirrors.tuna.tsinghua.edu.cn/apache/sqoop/1.4.6/ sqoop-1.4.6.bin__hadoop-2.0.4-alpha.ta ...

  8. 将属性和方法添加到Date原型中

    <button onclick="myFunction()">点我</button> <script> Date.prototype.myMet ...

  9. Linux 系统命令 - pwd - 显示当前所在的位置

    命令详解 重要星级: ★★★★★ 功能说明: pwd命令是 "print working directory" 中每个单词的首字母缩写,其功能是显示当前工作目录的绝对路径.在实际工 ...

  10. Windows 和 Linux 上Redis的安装守护进程配置

    # Windows 和 Linux 上Redis的安装守护进程配置 Redis 简介 ​ Redis是目前最常用的非关系型数据库(NOSql)之一,常以Key-Value的形式存储.Redis读写速度 ...