java8 笔记-Lambda表达式(一)

Java8

Lambda表达式

Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)

为什么需要Lambda表达式

在Java中,我们无法将函数作为参数传递给一个方法,也无法声明返回一个函数的方法。在JavaScript中,函数参数是一个函数,返回值是另一个函数的情况是非常常见的,JavaScript是一门典型的函数式语言。比如:

var lambda = function(x) { return x + 2 };
var result = lambda(function(x) { return x * x} (3) );
alert(result);
输出:
11

Lambda表达式优势:

  • 外部迭代 vs. 内部迭代
  • 传递行为,而不仅仅是传递值
  • 延迟加载

Java Lambda 语法结构

(param) -> { body }

(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
    statment1;
    statment2;
    //.............
    return statmentM;
}

特殊情况

  • 如果只有一个参数,可以省略小括号
param1 -> {
    statment1;
    statment2;
     //.............
    return statmentM;
}
  • 如果lambda表达式body只包含一条语句时,可以省略大括号、return和语句结尾的分号,也就是可以用表达式
param1 -> { statement; }
可以
param1 -> expression

Lambda第一个例子

这个例子看起来没什么特别,跟java8之前写法没看出区别,确实没区别,但我们的关注点在于forEach方法的参数Consumer,forEach方法(java8 Iterable添加的方法)接收一个Consumer类型的参数,Consumer接口上加了FunctionalInterface注解,Consumer接口只有一个抽象方法accept(接收一个参数不返回值),这种接口称为函数式接口。

public class LambdaTest {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("hello", "java8");

        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String value) {
                System.out.println(value);
            }
        });
    }
}
输出:
hello
java8

函数式接口 FunctionalInterface

Java Lambda与函数式接口息息相关,学习Java Lambda需要先了解函数式接口

Conceptually, a functional interface has exactly one abstract method.
However, the compiler will treat any interface meeting the regardless of whether or not a FunctionalInterface annotation is present on the interface declaration.

  • 一个接口中,有且仅有一个抽象方法
  • 如果一个接口符合函数式接口定义,不管它是否声明FunctionalInterface注解,编译器都会把它当作函数式接口
  • 如果一个接口声明了FunctionalInterface注解,那么编译器会按照函数接口的定义来要求该接口

创建函数式接口实例

Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references

函数式接口实例可以通过Lambda表达式,方法引用构造方法引用等创建,Comsumer是一个函数式接口,所以第一个例子可以通过Lambda表达式来创建。

public class LambdaTest {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("hello", "java8");

        list.forEach(value -> System.out.println(value));
    }
}
输出:
hello
java8

value -> System.out.println(value)的完整写法如下:

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

表示有一个输入参数,没有返回值,这与Consumer接口唯一的抽象方法accept方法签名是一致的,所以可以用value -> System.out.println(value) 表示Consumer。

默认方法

Consumer 接口还有一个方法andThen,并且有方法的实现,在java8之前,接口不可能有方法的实现,但是在java8之后,接口可以有方法的实现,但必须声明为default方法。java8为Iterable接口添加了方法forEach,如果Iterable不实现该方法,那么试想一下,用户老的代码实现了Iterable,然后用户升级到JDK1.8,肯定会报错,报接口有未实现的方法错误,为了兼容,所以java8提出了默认方法的概念。

Consumer的andThen方法,表示将两个Consumer进行组合,然后按照顺序执行两个Consumer的accept方法

 default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }

andThen例子:

先输出字符串的小写形式,然后输出大写

public class LambdaTest {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("Hello", "Java8");

        Consumer<String> consumer = value -> System.out.println(value.toLowerCase());

        Consumer<String> consumer2 = consumer.andThen(value -> System.out.println(value.toUpperCase()));

        list.forEach(consumer2);
    }
}
输出:
hello
HELLO
java8
JAVA8

Lambda示例说明:

示例说明
(int a, int b) -> {return a + b;}表示接收一个参数,返回一个值
() -> System.out.println(“hello java8”)表示不接收参数,不返回值
(String str) -> {System.out.println(str);}表示接收一个参数,不返回值
() -> 42;表示不接收参数,返回一个值
() -> {return 3.1415926;}表示不接收参数,返回一个值

例子

1、下面三个的输出是一样的:

    public static void main(String[] args) {

        List<String> list = Arrays.asList("hello", "java8");

        // 1. 标准写法
        list.forEach((String value) -> { System.out.println(value);});

        // 2.特殊情况,如果参数只有一个,可以省略小括号
        list.forEach(value -> { System.out.println(value);});

        // 3.如果方法体只有一个语句,可以省略大括号
        list.forEach(value -> System.out.println(value) );

    }
输出:
hello
java8
hello
java8
hello
java8

2、 将集合中的元素全部转换成大写

    public static void main(String[] args) {

        List<String> list = Arrays.asList("hello", "java8");

        list.forEach(value -> System.out.println(value.toUpperCase()));
    }
输出:
HELLO
JAVA8

3、Stream的例子

java8最重要的两块就是Lambda表达式和Stream,这里只是介绍几个简单的例子,后续会深入分析Lambda表达式和Stream

将集合中的所有字符串转换成大写

public static void main(String[] args) {

        List<String> list = Arrays.asList("hello", "java8", "welcome", "to", "java8", "world");

        list.stream().map(value-> value.toUpperCase()).forEach(value -> System.out.println(value));
输出:
HELLO
JAVA8
WELCOME
TO
JAVA8
WORLD

查找集合中字符串长度大于5的元素

    public static void main(String[] args) {

        List<String> list = Arrays.asList("hello", "java8", "welcome", "to", "java8", "world");

        list.stream().filter(value -> value.length() > 5).forEach(value -> System.out.println(value));
    }
输出:
welcome
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值