Java 8 Lambda Expressions by Examples

Ever since I heard Java 8 is going to support lambda expressions (aka
closures), I was very enthusiastic to spice my code with such a decent and
concise functional element. Most developers extensively use Anonymous Inner
Classes for event handlers, comparators, basic thread/runnable implementations,
etc and overburden the logic with unnecessary scaffoldings even a very simple
piece of code seems complex and unwieldy. Java 8 now added Lambda expressions as
part of language syntax that help solve similar problem in a very elegant
manner.

It enable developers to encapsulate a single unit of behavior and pass it to
other code. It’s like syntactic sugar for an anonymous class (with one method
whose type is inferred) and is an object-less method. I prefer avoiding
extensive theoretical material in this post, but before moving further towards
understanding the syntax, structure and examples of lambdas, there is an
important concept need attention.

Functional Interface

A Functional Interface (aka Single Abstract Method type or SMA) is any
interface that contains only one abstract method. But it may contain some static
or/and default methods. java.lang.Runnable is
an example of a Functional Interface, as it have only one run()
method, which is abstract. Similarly ActionListener interface is also a
functional interface. Following is an example of user defined functional
interface.





1

2

3

4

interface
Worker() {

    boolean
doWork();

};

Have a look at another templatized functional interface example:





1

2

3

4

interface
Operator {

    TYPE operate(TYPE operand1, TYPE operand2);

}

That’s it, as it’s a normal interface that just have one abstract method.
Although there is more to talk on functional interface specially java 8′s
provided package
java.util.function and
@FunctionalInterface annotation but for now just focus on lambdas.
I will cover these topic in detail in a separate post.

Lambda Expressions


Lambda expressions, also known as closures, are anonymous methods that
provide developers with a simple and compact means for representing behavior
as data.

- Brian Goetz, Specification Lead for JSR 335

To easily understand the syntax of a lambda expression we first take a look
at conventional Anonymous Inner Class.





1

2

3

4

5

6

7

new Runnable() {

    public
void run() {

        performWork();

    }

};

Lambda expressions provide the remedy for clumsiness of an Anonymous Inner
Class and convert above five lines into a single line like.





1

() -> performWork();

Syntax and Structure

So, standard syntax of lambda is as follows:





1

() -> some expression

Or





1

(arguments) -> { body just like function }

A lambda expression consists of the following three parts:

  1. A comma-separated list of formal parameters enclosed in parentheses.





    1

    2

    3

    4

    5

    // Taking two integers and retuning their sum

    (int
    x, int
    y) -> x + y

    // lambda expression with single integer argument that returns its next integer value

    (int
    x) -> { return
    x + 1; }

    You can omit the datatype of the parameters in a lambda expression.





    1

    2

    3

    4

    // same lambdas without argument types

    (x, y) -> x + y

    (x) -> { return
    x + 1; }

    In addition, you can omit the parentheses if there is only one
    parameter.





    1

    2

    // single argument lambda without parentheses

    x -> { return
    x + 1; }


  2. The arrow token, ->





    1

    2

    3

    4

    5

    //Lambda taking no argument and returning a constant integer vale, 92

    () -> 92

    // taking a string as an argument and printing that on console

    (String s) -> { System.out.println(s); }


  3. A body, which consists of a single expression or statement block. In the
    expression form, the body is simply evaluated and returned.





    1

    2

    3

    4

    5

    // for single statement body, no need to use braces and the return statement

    x -> x + 1

    // simple lambda with void return type

    () -> System.out.println(“Hello World!”)

    In the block form, the body is evaluated like a method body and a return
    statement returns control to the caller of the anonymous method.

Ok, we spend enough on syntax of lambda, let’s move to some real examples

Examples of Lambda Expressions

To easily understand the lambda expressions, let’s start with some basic
comparative examples with anonymous inner class. In the first example, we will
see the use of lambda Comparator interface implementation. Assume
we have a Person class with name property, and we constructed an
array of Person objects, named persons.





1

2

3

4

5

6

7

8

9

10

11

Arrays.sort(persons, new
Comparator() {

    @Override

    public
int compare(Person first, Person second) {

        return
first.getName().compareTo(second.getName());

    }

});

// it’s a standard sort but interestingly rather than passing Comparator object, it’s taking a lambda expression

Arrays.sort(persons,(first, second) -> first.getName().compareTo(second.getName()));

Notice that five lines of code turned into a single line, that’s the beauty
of lambda over anonymous inner classes. Now let’s look at another example of
Runnable implementation. And same is in the Runnable
case.





1

2

3

4

5

6

7

8

9

10

11

12

13

14

Runnable printer = new
Runnable() {

    @Override

    public
void run() {

        System.out.println("Hello, I’m inside runnable class...");

    }

};

printer.run();

printer = () -> System.out.println("Hello, I’m inside runnable lambda...");

printer.run();

Writing lambda expression for user defined functional interface is also very
simple and easy. Following example uses Operator custom interface
and stores lambda expression in a reference variable for the sake of
reusability;





1

2

3

Operator addition = (op1, op2) -> op1 + op2;

System.out.println("Addition result: "
+ addition.operate(2, 3));

For further understanding, there is another example of lambda expressions
with statement block.





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

interface
GenericOperator {

    TYPE operate(TYPE ... operands);

}

//lambda expression with statement block

GenericOperator multiply = numbers -> {

    int
result = 0;

    for(int
num : numbers)

        result *= num;

    return
result;

};

System.out.println("Multiplication result: "
+ multiply.operate(2,3,4));

As demonstrated above, the block is just like a normal function block and
lambdas are functional elements similar to methods, but with higher
significance.

When to use Lambda expression

Lambdas are not actually the replacement of anonymous inner classes but a
batter way to implement the single abstract method types. Both of them has their
significance and are intended to use in their specific scenarios.

  • Lambda expression are meant to implement a single unit of behavior that is
    intended to pass to other code.

  • Its usable when just simple instance of functional interface is desired,
    without having a type, constructor and related stuff.

  • On the other hand anonymous inner classes are used when new fields and
    functionality is required.

Lambda expressions and Anonymous inner classes


  • Anonymous classes introduce next level of scoping, whereas lambda
    expression are just like an enclosing environment. New variables with same
    name as in their super scope are allowed in classes whereas lambdas throw
    error and don’t allow that. Because they doesn’t introduce next level of
    scoping, local variable and fields/methods are directly accessible from
    enclosing scope.

  • Anonymous classes resolves this keyword to their own object,
    though lambda resolves it to enclosing class where it’s written. To access
    variables inside lambda from enclosing class, you can use
    this.

  • However, like anonymous classes, lambda expressions can only access local
    variables of the enclosing block that are final or effectively final. Access
    to non-final variables throws an error just like anonymous classes.

  • Serialization of lambda expressions are allowed only if its parameters and
    return type/target type are Serializable. Whereas its
    serialization is highly discouraged like anonymous classes.

  • Lambda expressions are compiled as private methods of enclosing class.
    Internally invokedynamic is used to bind methods dynamically,
    that were introduced in java 7.

Source Code

An IntelliJ project containing the source files for the examples covered in
the post.

source: http://zishanbilal.com/2014/05/08/java-8-lambda-expressions-examples/

时间: 2024-08-05 11:16:19

Java 8 Lambda Expressions by Examples的相关文章

java 8之Lambda Expressions 解说

java 8之Lambda Expressions 解说 java 8 新增Lambda Expressions 的目的:为了使代码简洁易读和消除过多的冗余代码(尽量让编译器做代码转换工作,也可以认为是语法糖之类的作用). 使用过c.c++语言的人,都记得,他们的函数参数可以是函数指针即代码片段(某些行为),而在java语言中,要想使得函数为参数,必须把函数封装成对象,以对象传参才可以.而 java 8 新增Lambda Expressions 使得这一现状得到缓解(函数式变成.闭包之类的概念都

Hacking Lambda Expressions in Java

Hacking Lambda Expressions in Javahttps://dzone.com/articles/hacking-lambda-expressions-in-java At the bytecode level, a lambda expression is replaced with an invokedynamic instruction. This instruction is used to create implementations of a function

Java 8 lambda表达式示例

例1.用lambda表达式实现Runnable 我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现Runnable接口是匿名类的最好示例.看一下Java 8之前的runnable实现方法,需要4行代码,而使用lambda表达式只需要一行代码.我们在这里做了什么呢?那就是用() -> {}代码块替代了整个匿名类. 1 // Java 8之前: 2 new Thread(new Runnable() { 3 @Override 4 public void run() {

深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)

转:http://zh.lucida.me/blog/java-8-lambdas-inside-out-library-features/ 关于 深入理解 Java 8 Lambda(语言篇--lambda,方法引用,目标类型和默认方法) 深入理解 Java 8 Lambda(类库篇--Streams API,Collector 和并行) 深入理解 Java 8 Lambda(原理篇--Java 编译器如何处理 lambda) 本文是深入理解 Java 8 Lambda 系列的第二篇,主要介绍

深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

最近看了一下java 8的一些新特性,其中最重要的莫过于Lambda表达式了,通过一阵子的学习,原本准备自己写一篇博客的,后来阅读了一位学长翻译过来的博客(原文是Brain Goetz的State of Lambda,下面会给出原文链接),觉得写的十分完美,把我想要写的和我没想到的都罗列了出来,就把这个分享给大家了. 注:原译文见  http://lucida.me/blog/java-8-lambdas-insideout-language-features/ 英语原版见:http://cr.

[转]深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)

以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-library-features 本文谢绝转载,如需转载需征得作者本人同意,谢谢. -------------------------------------内容分割线--------------------------------------------------------- 深入理解Java

[转]深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language-features 本文谢绝转载,如需转载需征得作者本人同意,谢谢. -------------------------------------内容分割线--------------------------------------------------------- 关于 本文是深入

Java 8 Lambda表达式10个示例【存】

PS:不能完全参考文章的代码,请参考这个文件http://files.cnblogs.com/files/AIThink/Test01.zip 在Java 8之前,如果想将行为传入函数,仅有的选择就是匿名类,需要6行代码.而定义行为最重要的那行代码,却混在中间不够突出.Lambda表达式取代了匿名类,取消了模板,允许用函数式风格编写代码.这样有时可读性更好,表达更清晰.在Java生态系统中,函数式表达与对面向对象的全面支持是个激动人心的进步.将进一步促进并行第三方库的发展,充分利用多核CPU.尽

[转载]深入理解Java 8 Lambda

原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language-features/ 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法) 2014年10月24日 | 评论 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://lucida.me/blog/java-8-lambdas-insideout-language-features/ 关于 深入理