从2014年java8发布到现在已经有几个年头了,现在java11都发布了。公司最近把服务器环境重新搭建了一遍,jdk版本也从7换成了8,终于可以在代码里面写Lambda表达式了。作为一名java开发人员,java8的一些新东西也是必须要掌握的,今天就说说这Lambda表达式的使用。

一、Lambda表达式简介

(1)定义
Lambda是一个匿名函数,我们可以把Lambda表达式理解为一段可以传递的代码。
优点:可以写出更简洁、更灵活的代码;同时它还是一种更紧凑的代码风格,使java的语言表达能力得到了提升
(2)看看代码
我们通过对比new一个Runnable的案例来对比使用Lambda表达式和不使用Lambda表达式的区别,代码如下:
	@Test
public void test01() {
// java7 new一个Runnable 匿名内部类
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("runnable java7");
}
}; // java8 new一个Runnable 使用了Lambda表达式,代码更紧凑了
Runnable r2 = () -> System.out.println("runnable java8"); // 开启线程
new Thread(r1).start();
new Thread(r2).start();
} @Test
public void test02() {
// java7 匿名内部类方式 新开一条线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("runnable java7 thread");
}
}).start(); // java8 使用了Lambda表达式 替代了匿名内部类,代码更简洁。
// 从这也能体现出Lambda表达式是一段可传递的代码(因为Lambda表达式等价于一个匿名内部类对象,所以可以当参数传递)
new Thread(() -> System.out.println("runnable java8 thread")).start();
}
32
32
 
1
    @Test
2
    public void test01() {
3
        // java7 new一个Runnable 匿名内部类
4
        Runnable r1 = new Runnable() {
5
            @Override
6
            public void run() {
7
                System.out.println("runnable java7");
8
            }
9
        };
10
        
11
        // java8 new一个Runnable  使用了Lambda表达式,代码更紧凑了
12
        Runnable r2 = () -> System.out.println("runnable java8");
13
        
14
        // 开启线程
15
        new Thread(r1).start();
16
        new Thread(r2).start();
17
    }
18
    
19
    @Test
20
    public void test02() {
21
        // java7 匿名内部类方式 新开一条线程
22
        new Thread(new Runnable() {
23
            @Override
24
            public void run() {
25
                System.out.println("runnable java7 thread");
26
            }
27
        }).start();
28
        
29
        // java8   使用了Lambda表达式 替代了匿名内部类,代码更简洁。
30
        // 从这也能体现出Lambda表达式是一段可传递的代码(因为Lambda表达式等价于一个匿名内部类对象,所以可以当参数传递)
31
        new Thread(() -> System.out.println("runnable java8 thread")).start();
32
    }
代码中new一个Runnable可以通过匿名内部类的方式,也可以采用Lambda的方式。但采用Labmbda方式的代码更简洁,可以让代码更紧凑。同时,匿名内部类对象是可以当成参数来直接传递的,Lambda表达式也可以用来当参数传。这就很好的解释了我们上面对Lambda的定义,即:【1】一个匿名函数,【2】一段可以传递的代码。

二、Lambda表达式的语法格式

        说语法格式之前,先来看张图吧。
    
    这图的左边是采用匿名内部类形式new的一个Runnable对象,右边是采用Lambda形式new的Runnable对象。对比一下就能领悟到Lambda表达式的语法格式啦。
(1)Lambda表达式标准格式
Lambda表达式个标准形式如下图:
Lambda表达式标准格式:左侧 -> 右侧
    左侧:指定了Lambda 表达式所需要的所有参数,即:形参列表。
    右侧:指定了Lambda 体,即:Lambda表达式要执行的功能。
(2)Lambda表达式语法格式一
左侧形参列表可以不需要参数的数据类型,java8后会根据上下文自动进行类型推断。
也就是说我们在Lambda的形参列表里面写的参数是可以不写数据类型的。具体案例见下图:
(3)Lambda表达式语法格式二
左侧形参列表只有一个参数时,小括号可以省略不写。不过一般建议还是写一下。
具体的案例见下图
(4)Lambda表达式语法格式三
左侧形参列表没有参数时,小括号必须保留
具体参考下面案例
这也是为什么在(3)中建议一个参数时也把小括号写上,写法统一一下。
(5)Lambda表达式语法格式四
右侧方法体中代码有多行时,需要用大括号包起来
具体看下图:
(6)Lambda表达式语法格式五
当右侧方法体中代码只有一行时,大括号可省略,同时return关键字也可以省略。
具体参考下图:

三、Lambda表达式vs匿名内部类

        看完这么多例子,感觉能用匿名内部类的地方就能用Lambda表达式。其实是不行的,不是所有能用匿名内部类的地方都可以用Lambda表达式来替代的。
下面我们来看个案例
(1)首先随便定义一接口
public interface TestFun {
// 这接口里面有2个抽象方法
void sayHello();
void end();
}
6
6
 
1
public interface TestFun {
2
    // 这接口里面有2个抽象方法
3
    void sayHello();
4
    void end();
5
}
6

(2)使用匿名内部类和Lambda表达式来创建这个接口的实例
	public static void main(String[] args) {
// 匿名内部类 == Lambda表达式 ? no .. // 匿名内部类
TestFun t1 = new TestFun() {
@Override
public void sayHello() {
System.out.println("hello");
}
@Override
public void end() {
System.out.println("end");
}
};
t1.sayHello();
t1.end(); // lambda 创建不了TestFun的实例对象,
// TestFun t2 = () -> {}
// 提示The target type of this expression must be a functional interface
// 因为 lambda表达式需要函数式接口
// 那什么是函数式接口, 我们可以去看看几个函数式接口Comparator、Runnable
// 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。 }
25
25
 
1
    public static void main(String[] args) {
2
        // 匿名内部类 == Lambda表达式 ?   no .. 
3
        
4
        // 匿名内部类
5
        TestFun t1 = new TestFun() {
6
            @Override
7
            public void sayHello() {
8
                System.out.println("hello");
9
            }
10
            @Override
11
            public void end() {
12
                System.out.println("end");
13
            }
14
        };
15
        t1.sayHello();
16
        t1.end();
17
        
18
        // lambda 创建不了TestFun的实例对象,
19
        // TestFun t2 = () -> {}
20
        // 提示The target type of this expression must be a functional interface
21
        // 因为 lambda表达式需要函数式接口
22
        // 那什么是函数式接口,  我们可以去看看几个函数式接口Comparator、Runnable
23
        // 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
24
        
25
    }
在写代码过程中发现Lambda表达式创建不了这种接口里面有多个抽象方法的对象,而匿名内部类可以。
在使用Lambda表达式时eclipse直接提示了一个错误,错误消息见下图:
这个弹窗的提示说目标类型必须是函数式接口。
(3)小结
    通过上面这个案例,我们发现并不是所有能用匿名内部类的地方都可以用Lambda表达式来替代。
Lambda表达式只能用来替代那些函数式接口的匿名内部类。那什么是函数式接口呢?继续往下看吧

四、函数式接口

(1)定义
从java8实战这书中读到了函数式接口的定义如下:
一言以蔽之,函数式接口就是只定义一个抽象方法的接口
1
1
 
1
一言以蔽之,函数式接口就是只定义一个抽象方法的接口
上面这个定义已经很言简意赅了,函数式接口就是只有一个抽象方法的接口

(2)说说常用的函数式接口
直接可以去看jdk的java.util.function包下面看,都是函数式接口。常用的函数式接口如下:
  • 消费型接口Consumer
        它有一个抽象方法,形参列表为一个参数,没有返回值。具体的参考下面代码的案例
    /**
* 消费型接口Consumer
*/
@Test
public void test01() {
/*
* Consumer是一个消费型接口
* (1)该接口的抽象方法为void accept(T t);
* (2)这个抽象方法形参列表有一个参数,没有返回值;
* (3)这个方法就是一个有数据进去,没数据返回的接口; 所以就叫它消费型接口
*/
Consumer<String> c = (x) -> {
System.out.println(x);
System.out.println("length is:" + x.length());
};
c.accept("hello"); // 我们传一个hello给它,将会在控制台中打印出hello及它的长度
}
17
17
 
1
    /**
2
     * 消费型接口Consumer
3
     */
4
    @Test
5
    public void test01() {
6
        /*
7
         *  Consumer是一个消费型接口
8
         *  (1)该接口的抽象方法为void accept(T t);
9
         *  (2)这个抽象方法形参列表有一个参数,没有返回值;
10
         *  (3)这个方法就是一个有数据进去,没数据返回的接口; 所以就叫它消费型接口
11
         */
12
        Consumer<String> c = (x) -> {
13
            System.out.println(x);
14
            System.out.println("length is:" + x.length());
15
        };
16
        c.accept("hello");  // 我们传一个hello给它,将会在控制台中打印出hello及它的长度
17
    }
  • 断言型接口Predicate
        它有一个抽象方法,形参列表为一个参数,返回值为boolean类型。特别适合条件判断的场景,具体的参考下面代码的案例
    /**
* 断言型接口Predicate
*/
@Test
public void test02() {
/*
* Predicate是一个断言型接口
* (1)该接口的抽象方法为boolean test(T t);
* (2)这个抽象方法形参列表有一个参数,返回值为boolen;
* (3)这个方法就是一个有数据进去,返回true或者false; 特别适合用来做条件判断的场景
*/
// 下面演示一个过滤集合里面元素的案例,过滤掉集合里面小于5的元素
List<Integer> list = listFilter(Arrays.asList(new Integer[]{12, 2, 3, 10, 25}), x -> x >= 5);
System.out.println(list); // 输出 [12, 10, 25]
} /**
* 定义的一个集合过滤方法
* @param list 集合
* @param predicate 断言型接口,用来里面包含了过滤的条件
* @return
*/
private <T> List<T> listFilter(List<T> list, Predicate<T> predicate) {
List<T> result = new ArrayList<T>();
for (T t : list) {
if (predicate.test(t)) {
result.add(t);
}
}
return result;
}
32
32
 
1
    /**
2
     * 断言型接口Predicate
3
     */
4
    @Test
5
    public void test02() {
6
        /*
7
         *  Predicate是一个断言型接口
8
         *  (1)该接口的抽象方法为boolean test(T t);
9
         *  (2)这个抽象方法形参列表有一个参数,返回值为boolen;
10
         *  (3)这个方法就是一个有数据进去,返回true或者false; 特别适合用来做条件判断的场景
11
         */
12
        // 下面演示一个过滤集合里面元素的案例,过滤掉集合里面小于5的元素
13
        List<Integer> list = listFilter(Arrays.asList(new Integer[]{12, 2, 3, 10, 25}), x -> x >= 5);
14
        System.out.println(list);   // 输出 [12, 10, 25]
15
    }
16

17
    /**
18
     * 定义的一个集合过滤方法
19
     * @param list      集合
20
     * @param predicate 断言型接口,用来里面包含了过滤的条件
21
     * @return
22
     */
23
    private <T> List<T> listFilter(List<T> list, Predicate<T> predicate) {
24
        List<T> result = new ArrayList<T>();
25
        for (T t : list) {
26
            if (predicate.test(t)) {
27
                result.add(t);
28
            }
29
        }
30
        return result;
31
    }
32

更多函数式接口,可以直接看java.util.function包里面的内容。


Java8_Lambda表达式的更多相关文章

  1. 【.net 深呼吸】细说CodeDom(2):表达式、语句

    在上一篇文章中,老周厚着脸皮给大伙介绍了代码文档的基本结构,以及一些代码对象与CodeDom类型的对应关系. 在评论中老周看到有朋友提到了 Emit,那老周就顺便提一下.严格上说,Emit并不是针对代 ...

  2. 你知道C#中的Lambda表达式的演化过程吗?

    那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传递方法的类型.(用来传递数字的类型有int.float ...

  3. 再讲IQueryable<T>,揭开表达式树的神秘面纱

    接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...

  4. Linq表达式、Lambda表达式你更喜欢哪个?

    什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...

  5. 背后的故事之 - 快乐的Lambda表达式(一)

    快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...

  6. Kotlin的Lambda表达式以及它们怎样简化Android开发(KAD 07)

    作者:Antonio Leiva 时间:Jan 5, 2017 原文链接:https://antonioleiva.com/lambdas-kotlin/ 由于Lambda表达式允许更简单的方式建模式 ...

  7. SQL Server-表表达式基础回顾(二十四)

    前言 从这一节开始我们开始进入表表达式章节的学习,Microsoft SQL Server支持4种类型的表表达式:派生表.公用表表达式(CTE).视图.内嵌表值函数(TVF).简短的内容,深入的理解, ...

  8. 立即执行函数表达式(IIFE)

    原文地址:benalman.com/news/2010/11/immediately-invoked-function-expression/ 译者:nzbin 也许你还没有注意到,我是一个对术语比较 ...

  9. javascript:逆波兰式表示法计算表达式结果

    逆波兰式表示法,是由栈做基础的表达式,举个例子: 5 1 2 + 4 * + 3 -  等价于   5 + ((1 + 2) * 4) - 3 原理:依次将5 1 2 压入栈中, 这时遇到了运算符 + ...

随机推荐

  1. JAVA爬虫---验证码识别技术(一)

    Python中有专门的图像处理技术比如说PIL,可以对验证码一类的图片进行二值化处理,然后对图片进行分割,进行像素点比较得到图片中的数字.这种方案对验证码的处理相对较少,运用相对普遍,很多验证码图片可 ...

  2. iOS多线程系统整理 swift

    多线程   是一个应用程序内多个代码的执行路径,执行线程,同时在同一时间里执行不同的任务. 三种: 1.NSTread 2.Cocoa NSOperation (NSOperation,NSOpera ...

  3. androidStudio修改包名 Android 如何修改包名(同一个手机可以跑2个eros 项目)。

    修改applicationId(gradle.properties). 2.即时同步更新过去,否则不报错

  4. Visual Studio 2010 vs2010 英文版 使用 已有的中文版 MSDN 帮助文档

    第一步 设置Help Library Manager区域语言 打开Microsoft Visual Studio 2010开始菜单里Visual Studio Tools里的Manage Help S ...

  5. python any all函数

    a = [0, 0, 0, 0] b = [0, 0, 0, 1] c = [1, 1, 1, 1] >>> any(a) False >>> any(b) Tru ...

  6. LeetCode Excel Sheet Column Number 表列数

    题意:天啊!我竟然看不懂题意,还去翻别人的代码才懂!给定一个字符串,求该字符串二十六进制的总值. 思路:'A'~'Z'就是1到26,"AA"=26+1=27,"BA&qu ...

  7. java 串口通信实现流程

    1.下载64位rxtx for java 链接:http://fizzed.com/oss/rxtx-for-java 2.下载下来的包解压后按照说明放到JAVA_HOME即JAVA的安装路径下面去 ...

  8. 【BZOJ4033】[HAOI2015] 树上染色(树形DP)

    点此看题面 大致题意: 给你一棵点数为N的带权树,要你在这棵树中选择K个点染成黑色,并将其他的N-K个点染成白色.要求你求出黑点两两之间的距离加上白点两两之间距离的和的最大值. 树形\(DP\) 这道 ...

  9. 对ListBox控件中的数据进行排序

    实现效果: 知识运用: ListBox控件的Sorted属性 //ListBox控件中的数据项是否按字母顺序排序 public bool Sorted{get;set;} 实现代码: private ...

  10. CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第四节

    了解和使用共享内存(1) Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在多个国家级的实验室进行大型并行运 ...