Java Lambda表达式

本文深入探讨Java Lambda表达式的基础知识,包括匿名类、匿名函数的概念,以及如何使用Lambda表达式简化代码。通过实例展示了Lambda表达式在筛选苹果任务中的灵活应用,比较了传统方法与Lambda表达式的优劣。
摘要由CSDN通过智能技术生成


最近在学Java8的知识, 发现哪怕是自己会的Java基础还是远远不够的

匿名类和匿名函数

我们知道, Java是一门纯面向对象的语言, 对象是第一等公民, 意思是对象可以作为参数传递. 在很多语言中, 有一个概念, 叫做函数式编程, 函数也是一等公民, 也就是说函数也可以像对象啊一样作为参数传递, 这是怎么回事呢
首先, 让我们回顾一下匿名类. 在以前, 我们用Runnable定义线程先定义一个实现了Runnable接口的类, 然后传递到一个Thread对象中:

public class Test implements Runnable{
	@Override
    public boolean run() {
        System.out.println("Hello world!");
    }
}


public class Main{
    public static void main(String[] args) {
    	Thread thread = new Thread(new Test());
    }
}

之后我们可以用匿名类减少代码量:

public class Main{
    public static void main(String[] args) {
    	Thread thread = new Thread(new Runnable(){
    		@Override
    		public boolean run() {
        		System.out.println("Hello world!");
    		}
    	});
    }
}

但是, 匿名类的代码依然很长, 而且也不好理解(至少我当时就理解了很久…). 现在, 我们先试着使用匿名函数, 也就是lambda表达式:

public class Main{
    public static void main(String[] args) {
    	Thread thread = new Thread(() -> System.out.println("Hello World!"));
    }
}

这样代码就更加简洁了.

Lambda表达式

在上述例子中, 我们见到了() -> System.out.println("Hello World!"), 这就是匿名函数, 也就是Lambda表达式, 我们使用Lambda表达式前必须先有函数式接口, 什么事函数式接口呢? 函数式接口就是只定义了一个抽象方法的接口. 上述例子中Runnable接口只有一个run()抽象方法, 所以它是一个函数式接口. 那么, Lambda表达式怎么书写呢?
在Lambda表达式中, ()里是参数, -> 后面是函数体, 如果函数有多行, 则需要将其用花括号包起来. 对于函数式接口, 我们都可以用Lambda表达式来代替, 但是只有函数描述符一致才行. 什么是函数描述符呢?

函数描述符

在有些语言中, 函数也是一个变量, 他们的类型是类似于()->void的东西, 这一个表达式说明这是一个无参数无返回值的函数, 同理(int)->String表示有一个变量为整型, 返回值为字符串的函数. 这个在java中就是函数描述符, 只要函数描述符和接口中的抽象方法一致时, Lambda表达式才是有效的.
对于只有一行的带返回值的Lambda表达式, 我们可以将return隐去, 下面两个式子是等价的:

(int a, int b) -> {return a + b}
(int a, int b) -> a + b

Lambda表达式应用

说了这么多, Lambda到底好用在哪里呢? 我们用下面一个例子来说明它的用法:
假设我们要从一堆苹果中进行筛选, 筛选出所有红色的苹果, 我们写了一下代码:

    public List<Apple> filterApples(List<Apple> inventory) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if ("red".equals(apple.getColor())) {
                result.add(apple);
            }
        }
        return result;
    }

之后, 我们收到了新的要求: 筛选所有质量大于150的苹果, 于是我们书写了一下代码:

    public List<Apple> filterApples(List<Apple> inventory) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if (apple.getWeight() > 150) {
                result.add(apple);
            }
        }
        return result;
    }

其实这个术后已经有冗余了. 之后又有了新要求: 同事筛选红色和重于150的苹果, 于是我们写下了下面一个接口:

    public interface Predicate {
       boolean test();
    }

之后我们只要实现这个接口就好了:

 public class AppleRedColorPredicate implements ApplePredicate {
    @Override
    public boolean test(Apple apple) {
        return "red".equals(apple.getColor());
    }
}

public class AppleHeavyPredicate implements ApplePredicate {
    @Override
    public boolean test(Apple apple) {
        return apple.getWeight() > 150;
    }
}

然后修改 filterApples() 方法:

    public List<Apple> filterApples(List<Apple> inventory, ApplePredicate applePredicate) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            // 根据删选方法删选苹果
            if (applePredicate.test(apple)) {
                result.add(apple);
            }
        }
        return result;
    }

但是每次都写一个实现类实在是太麻烦了, 这个时候Lambda表达式的好处就体现出来了, 我们根据要求传递匿名函数进去就行了, 根本就不需要写实现类:
删选红苹果:

public void test(List<Apple> inventory) {
	List<apple> result = filterApples(inventory, (Apple apple) -> "red".equals(apple.getColor());
}

删选重苹果:

public void test(List<Apple> inventory) {
	List<apple> result = filterApples(inventory, (Apple apple) -> apple.getWeight() > 150;
}

删选又红又重的苹果:

public void test(List<Apple> inventory) {
	List<apple> result = filterApples(inventory, (Apple apple) -> "red".equals(apple.getColor()) && apple.getWeight() > 150;
}

Lambda表达式的用处还有很多, 这就需要我不断学习不断摸索了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值