文档章节

Java Lambda入门学习

钟声已经敲响
 钟声已经敲响
发布于 2016/10/24 18:38
字数 1509
阅读 139
收藏 6

感觉Lambda表达式写起来确实很简洁,今天就简单看了一下Lambda表达式。在Java 8,一个重要的变更是引入Lambda表达式(lambda expression),这听起来似乎很牛,有种我虽然不知道Lambda表达式是什么,但我仍然觉得很厉害的感觉。具体到语言层面上Lambda表达式不过是一种新的语法而已,下面就一起敲开Java函数式编程的大门。

 

Lambda表达式

 

到底什么是Lambda表达式、什么是函数式编程。先来看一下Java 8新的语法特性带来的便利之处,相信你会受益匪浅。

不用Lambda表达式新起一个线程,如下:

new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread second run test");
            }
        }).start();

Lambda表达式就由可以这样写:

  new Thread(
                () -> System.out.println("Thread first run()")
        ).start();

 

可以看出,匿名类消失了。可见,lambda expression一个常见的用法是取代(某些)匿名内部类,但Lambda表达式的作用不限于此。

 

lambda expression表达式的原理

  • Lambda表达式可以包含多行代码,需要用大括号把代码块括起来,就像写函数体那样。如
         //可以放多行代码 以 大括号扩起
            new Thread(
                    () -> {
                        System.out.println("Thread test111");
                        System.out.println("Thread test222");
                    }
            ).start();

     

  • Lambda表达式是有类型的,赋值操作的左边就是类型。Lambda表达式的类型实际上是对应接口的类型。
  • Lambda表达式的参数表可以省略类型,就像代码2和5那样。这得益于javac的类型推导机制,编译器可以根据上下文推导出类型信息。

所以,就有如下:

Runnable run = () -> System.out.println("Hello World");
ActionListener listener = event -> System.out.println("test clicked");// 2
Runnable multiLine = () -> {// 3
    System.out.println("Hi ");
    System.out.println("boy");
};
BinaryOperator<Long> add = (Long x, Long y) -> x + y;// 4
BinaryOperator<Long> addImplicit = (x, y) -> x + y;// 5

 

表面上看起来每个Lambda表达式都是原来匿名内部类的简写形式,该内部类实现了某个函数接口(Functional Interface),但事实比这稍微复杂一些,这里不再展开。所谓函数接口是指内部只有一个接口函数的接口。Java是强类型语言,无论有没有显式指明,每个变量和对象都必须有明确的类型,没有显式指定的时候编译器会尝试确定类型。Lambda表达式的类型就是对应函数接口的类型

比如,Runnable的函数式注解如下:

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

 

 

天做之合-------Lambda和Stream的结合使用

Lambda表达式的另一个重要用法,是和Stream一起使用。Stream is a sequence of elements supporting sequential and parallel aggregate operations。Stream就是一组元素的序列,支持对这些元素进行各种操作,而这些操作是通过Lambda表达式指定的。可以把Stream看作Java Collection的一种视图,就像迭代器是容器的一种视图那样(但Stream不会修改容器中的内容)。下面例子展示了Stream的常见用法。

例1:

假设需要从一个字符串列表中选出以数字开头的字符串并输出,Java 8之前需要这样写:

List<String> list = Arrays.asList("1one", "two", "three", "4four");
for(String str : list){
    if(Character.isDigit(str.charAt(0))){
        System.out.println(str);
    }
}

而在Java 8就可以这样写:


        strList.stream()// 1.得到容器的Steam
                .filter(str -> Character.isDigit(str.charAt(0)))// 2.选出以数字开头的字符串
                .forEach(str -> System.out.println(str));// 3.输出字符串

上述代码首先1. 调用List.stream()方法得到容器的Stream,2. 然后调用filter()方法过滤出以数字开头的字符串,3. 最后调用forEach()方法输出结果。

 

例2:

假设需要从一个字符串列表中,选出所有包含own的字符串,将其转换成大写形式,并把结果放到新的集合当中。

java8之前的代码我就不写了,直接用java8看吧,具体如下:

  List<String> testList = Arrays.asList("1owne", "twown", "three", "4fownur");
        Set<String> newList =
                testList.stream()// 1.得到容器的Stream
                        .filter(str -> str.contains("o"))// 2.选出不以数字开头的字符串
                        .map(String::toUpperCase)// 3.转换成大写形式
                        .collect(Collectors.toSet());// 4.生成结果集

        newList.stream().forEach(str -> System.out.println(str));//5.输出结果

上述代码首先
            1. 调用List.stream()方法得到容器的Stream,
            2. 然后调用filter()方法选出不以数字开头的字符串,
            3. 之后调用map()方法将字符串转换成大写形式,
            4. 最后调用collect()方法将结果转换成Set。
            5. 用forEach输出结果。
            例子中还展示了方法引用(method references,代码中标号3处)以及收集器(Collector,代码中标号4处)的用法,这里不再展开,有兴趣可以自行查资料看看。


通过这个例子我们看到了Stream链式操作,即多个操作可以连成一串。不用担心这会导致对容器的多次迭代,因为不是每个Stream的操作都会立即执行。Stream的操作分成两类,一类是中间操作(intermediate operations),另一类是结束操作(terminal operation),只有结束操作才会导致真正的代码执行,中间操作只会做一些标记,表示需要对Stream进行某种操作。这意味着可以在Stream上通过关联多种操作,但最终只需要一次迭代。

可以看出,Stream的明显优势:

  • 减少了模板代码,只用Lambda表达式指明所需操作,代码语义更加明确、便于阅读。
  • 将外部迭代改成了Stream的内部迭代,方便了JVM本身对迭代过程做优化(比如可以并行迭代)。

github测试代码:https://github.com/wangtao1/functional-lambda.git

借阅:

1.https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
2.http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html
3.https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html

 

 

 

 

 

 

 

 

© 著作权归作者所有

上一篇: git常用命令
钟声已经敲响
粉丝 12
博文 36
码字总数 32502
作品 0
海淀
程序员
私信 提问
尝试Java,从入门到Kotlin

之前一直使用C#开发,最近由于眼馋Java生态环境,并借着工作服务化改造的契机,直接将新项目的开发都转到Java上去。积攒些Java开发经验,应该对.NET开发也会有所启发和益处。 欢迎工作一到八...

编程SHA
2018/12/03
27
1
一份关于 Java、Kotlin 与 Android 的学习笔记

JavaKotlinAndroidLearn 这是一份关于 Java 、Kotlin 、Android 的学习笔记,既包含对基础知识点的介绍,也包含对一些重要知识点的源码解析,笔记的大纲如下所示: Java 重拾Java(0)-基础知...

叶应是叶
2018/08/08
0
0
Java 8里面lambda的最佳实践

Java 8已经推出一段时间了,越来越多开发人员选择升级JDK,这条热门动弹里面看出,JDK7最多,其次是6和8,这是好事! 在8 里面Lambda是最火的主题,不仅仅是因为语法的改变,更重要的是带来了...

OSC闲人
2015/04/30
9.9K
41
Lambda 表达式有何用处?如何使用?(针对Java8)

什么是Lambda? 我们知道,对于一个Java变量,我们可以赋给其一个“值”。 如果你想把“一块代码”赋给一个Java变量,应该怎么做呢? 比如,我想把右边那块代码,赋给一个叫做aBlockOfCode的J...

亭子happy
2018/06/06
330
2
【Java学习路线】新手该如何一步步的学习 Java

新手该如何一步步的学习 Java? 如果真的想学Java,最好要循序渐进,有章有法的学习它! 今天小慕就不说一些学习方法和技巧了,直接来谈每个阶段要学习的内容。 首先,给大家分享一张以 企业...

Eddie_yang
2018/11/15
2.4K
0

没有更多内容

加载失败,请刷新页面

加载更多

开发中常用的正则表达式

为了能够更好地理解如何在C#环境中使用正则表达式,这里整理了一些常用的正则表达式: 罗马数字: string p1 = "^m*(d?c{0,3}|c[dm])" + "(l?x{0,3}|x[lc])(v?i{0,3}|i[vx])$"; string t1 =......

木庄
12分钟前
4
0
【.NET程序打包】VS2019使用Installer Projects打包

C#—使用Installer Projects打包桌面应用程序 前言 打包桌面应用程序实在是一个不常使用的东西,偶尔使用起来经常会忘东忘西的耽误时间,因此,这篇文章多以图片记录过程,也是用于备忘。 下...

_Somuns
17分钟前
4
0
自定义注解,使用动态代理解决网站的字符集编码问题

第1章设置环境 安装操作系统,安装备份(镜像): JDK: 设置环境变量Eclipse:解压即可 Eclipse自身解压目录不包括中文 代码工作空间目录不包括中文Tomcat:解压不要包含中文目录M...

蓝来杯往
21分钟前
3
0
Solr中的字段类型field type

Solr含有多种字段类型,可用的字段类型基本都定义在了包org.apache.solr.schema中,列举如下: 类 说明 BinaryField 二进制数据 BoolField 布尔值,其中’t’/’T’/’1’都是true Collatio...

gantaos
35分钟前
4
0
《JAVA核心知识》学习笔记 (21. JAVA 算法)

21. JAVA 算法

Shingfi
42分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部