Java8 新特性

lambda表达式

什么是lambda表达式

Java 是面向对象的语言,一切皆对象,Java中的方法不能够单独存在,将方法作为参数传入需要用到匿名内部类,为了解决这一问题,Java8增加了新特性,即Lambda表达式。

lambda表达式实现原理

函数式接口

可以通过Lambda表达式来创建该接口的对象

@FunctionalInterface
interface IFunctionTest<T> {
    public void print(T x);
}

函数式接口只允许声明一个抽象方法

@FunctionalInterface
interface IFunctionTest<T> {
    public void print(T x);

    default void print1(T x){};

    static void print2() {};

    @Override
    boolean equals(Object obj);
}

额外声明default,static或者是override方法是可以的。

Lambda表达式的运行原理又是怎样的呢?

  • 首先,在类编译时,会生成一个私有静态方法+一个内部类;
  • 内部类实现函数式接口,在实现接口的方法中,会调用编译器生成的静态方法;
  • 在使用lambda表达式的地方,通过传递内部类实例,来调用函数式接口方法。

以上可以通过反编译代码来验证,具体可参考https://www.cnblogs.com/WJ5888/p/4667086.html

lambda表达式使用场景

现有一Person类

package lambda.usage;

import java.time.LocalDate;

public class Person {

    public enum Sex {
        MALE, FEMALE
    }

    /**
     * 字段说明省略
     */
    String name;

    LocalDate birthday;

    Sex gender;

    String email;
}

现有List<Person> ,需求是从List中筛选合适的Person。
在没有lambda之前有以下几种解决方案

  1. 直接写方法
  2. 实现接口
  3. 匿名内部类

方案1,2,3都可以实现需求,但是如果使用方案1,2要实现多个筛选条件,就要实现多个方法,那么有没有更简洁的方式呢,过去我们用匿名内部类实现,例如我们想筛选出女性,代码如下。

		interface PersonFilter<T>{
		    boolean filter(T t);
		}
		public static boolean filter(Person p, PersonFilter<Person> PersonFilter) {
		    return PersonFilter.filter(p);
		}
		//筛选女性
        List<Person> females = new ArrayList<>();
        for (Person person : people) {
            if (filter(person, new PersonFilter<Person>() {
                @Override
                public boolean filter(Person person) {
                    return Person.Sex.FEMALE.equals(person.getGender());
                }
            })) {
                females.add(person);
            }
        }

可以看出,使用匿名内部类可以解决以上问题,但是程序看起来并不简洁,那么有没有更好的方案呢?

在引入lambda表达式后,我们可以这样做。

        for (Person person : people) {
            if (filter(person, p -> p.getGender().equals(Person.Sex.FEMALE))){
                females.add(person);
            }
        }

除此之外,PersonFilter是一个非常简单的接口。它只包含了唯一的抽象方法因而它是一个函数接口。该方法接收一个参数并返回一个boolean值。该方法是如此的简单以至于没有必要在应用程序中进行定义。 因此,JDK中的java.util.function包中定义了很多标准的函数接口。

例如,我们可以使用Predicate接口来代替PersonFilter

	    public static boolean filter(Person p, Predicate<Person> PersonFilter) {
	        return PersonFilter.test(p);
	    }

那么,为什么可以这样用呢?原因很简单,这是Predicate接口中test()的源码。

		boolean test(T t);

同理,如果想传入一个返回void方法,可以使用Consumer<T>接口的accept()方法。如果想传入一个带有返回值的方法,可以使用Function<T, R>接口的apply(T t)方法。

还可以使用泛型,下面代码的功能是打印女同志的姓名

    public static <X, Y> void processPerson(
            Iterable<X> source,
            Predicate<X> tester,
            Function<X, Y> mapper,
            Consumer<Y> block) {
            for(X x : source) {
                if (tester.test(x)) {
                    Y data = mapper.apply(x);
                    block.accept(data);
                }
            }
    }
    
       processPerson(
               people,
               p -> Person.Sex.FEMALE.equals(p.getGender()),
               p -> p.getName(),
               name -> System.out.println(name)
       );

除此之外,还可以使用聚集操作来实现此功能,代码如下。

        people.stream()
                .filter(person -> Person.Sex.FEMALE.equals(person.getGender()))
                .map(person -> person.getName())
                .forEach(name -> System.out.println(name));

lambda表达式语法

lambda表达式有以下几个部分组成

  1. 形参列表:参数类型可省略,如果只有一个参数括号也可省略。
  2. 箭头: ->
  3. 主体:{}, 如果写return,花括号不可省

访问外围作用域中的局部变量

使用this关键字

参考自:
http://tutorials.jenkov.com/java/lambda-expressions.html
https://blog.csdn.net/code_for_fun/article/details/42169993

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值