Java Lambda Expression

本文通过实例详细介绍了Java SE8引入的Lambda表达式,展示了如何使用Lambda表达式改进代码的灵活性和可维护性,包括使用匿名类、自定义接口及标准FunctionalInterface等多种方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

I. 简介

在Java 更新SE8后,加入了Lambda 表达式,给Java 增加了一些动态编程的元素,在一定程度上便利了开发.
本篇将会使用一个实例来说明和演示Lambda Expression 的操作。例子和说明皆来自官方Lambda Expression Tutorial

II. 实例

假设现在设计了一个Person 类,用于储存用户的信息。

public class Person {
    private Sex sex;
    private int age;
    private String name;
    private String email;
    private Date birthDate;

    public Person(Sex sex, String email, 
            String name, Date brithDay, int age) {
        this.sex = sex;
        this.email = email;
        this.name = name;
        this.birthDate = birthDate;
    }

    public Person() {
        this(null, null, null, null, 0);
    }

    public int getAge() { return age; }

    public String getName() { return name; }

    @Override
    public String toString() {
        return this.getName() + "   age: " + this.getAge()
                + "   sex: " + sex.getSex();
    }
}

public class Sex {
    private boolean sex; // true: female
                        // false: male

    private Sex(boolean sex) {
        this.sex = sex;
    }

    public Sex generate(boolean sex) {
        return new Sex(sex);
    }

    public String getSex() {
        if (sex)
            return "female";
        else return "male";
    }

    @Override
    public String toString() {
        if (sex)
            return "female";
        else return "male";
    }
}

现在有一个方法,printPerson()用于找到适合条件的人,并在控制台中输出.
这里的判断条件为年龄大于等于18并小于等于25.

    public static void printPerson(Iterable<Person> roster) {
        for (Person p: roster) {
            if (18 <= p.getAge() && p.getAge() <= 25)
                System.out.println(p);
        }
    }

但是这个方法按照此设计不符合设计要求,即将不变的元素与变化的元素分离开来:如果程序更新后printPerson()的判断条件要改变,或是在不同情景下有不同的判断标准,唯一的选择只有重写多个方法.

改进方法1 参数变化

    public static void printPersonOlderthan
        (Iterable<Person> roster, int low, int high) {
        for (Person p: roster) 
            if (low <= p.getAge() && p.getAge() <= high)
                System.out.println(p);
    }

新的方法printPersonOlderthan()接收两个参数,根据两个参数提供的条件判断,这在一定程度上试方法更加灵活了.

改进方法2 接口

public interface CheckPerson {
    public boolean check(Person person);
}

public class CheckPersonEligibleForService 
                implements CheckPerson {
    @Override
    public boolean check(Person person) {
        return 18 <= person.getAge() && person.getAge() <= 25;
    }
}

不依靠传入参数,而是通过传入接口来决定选择的标准并执行接口,进一步提升了程序的灵活性.
现在,Person 类中的printPerson()方法的参数传入的是CheckPerson接口.

    public static void printPersonWithInterface
        (Iterable<Person> roster, CheckPerson checkPerson) {
        for (Person p: roster)
            if (checkPerson.check(p))
                System.out.println(p);
    }

现在,只要根据需求执行CheckPerson接口就可以了.

改进方法3 匿名类

如果某个判断标准只会用到一次,那么使用匿名类能够减少程序hierarchy.

    public static void main(String [] args) {
        List<Person> persons = new ArrayList<>(20);
        printPersonWithInterface(persons, new CheckPerson() {
            @Override
            public boolean check(Person person) {
                return 18 <= person.getAge()
                        && person.getAge() <= 25;
            }
        });
    }

改进方法4 Lambda 表达式

相对于实现匿名类,Lambda 表达式会更适合当前场景,尤其是执行只有一个方法的Functional Interface时(Functional Interface 只含一个方法或多个default 方法).

    public static void main(String [] args) {
        List<Person> persons = new ArrayList<>(20);
        printPersonWithInterface(persons, 
            (p) -> 18 <= p.getAge() && p.getAge() <= 25);
    }

现在,代码的长度大大的简化了.

改进方法5 使用标准Functional Interface

相比起使用自己定义的CheckPerson接口,Java SE8 提供了官方的Functional Interface,Predicate < T >.

    public static void 
    printPersonWithStandardInterface
    (Iterable<Person> roster, Predicate<Person> test) {
        for (Person p: roster)
            if (test.test(p))
                System.out.println(p);
    }

    public static void main(String [] args) {
        List<Person> persons = new ArrayList<>(20);
        printPersonWithStandardInterface(persons, 
            (p) -> 18 <= p.getAge() && p.getAge() <= 25);
    }

处了Predicate 外,官方提供了Function, Consumer,具体用途可自行查阅API.

III. Syntax of Lambda

不想写了,就直接粘贴复制了orz

A lambda expression consists of the following:

A comma-separated list of formal parameters enclosed in parentheses. The CheckPerson.test method contains one parameter, p, which represents an instance of the Person class.

Note: You can omit the data type of the parameters in a lambda expression. In addition, you can omit the parentheses if there is only one parameter. For example, the following lambda expression is also valid:

p -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
The arrow token, ->

A body, which consists of a single expression or a statement block. This example uses the following expression:

p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
If you specify a single expression, then the Java runtime evaluates the expression and then returns its value. Alternatively, you can use a return statement:

p -> {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
A return statement is not an expression; in a lambda expression, you must enclose statements in braces ({}). However, you do not have to enclose a void method invocation in braces. For example, the following is a valid lambda expression:

email -> System.out.println(email)
Note that a lambda expression looks a lot like a method declaration; you can consider lambda expressions as anonymous methods—methods without a name.

The following example, Calculator, is an example of lambda expressions that take more than one formal parameter:

public class Calculator {

interface IntegerMath {
    int operation(int a, int b);   
}

public int operateBinary(int a, int b, IntegerMath op) {
    return op.operation(a, b);
}

public static void main(String... args) {

    Calculator myApp = new Calculator();
    IntegerMath addition = (a, b) -> a + b;
    IntegerMath subtraction = (a, b) -> a - b;
    System.out.println("40 + 2 = " +
        myApp.operateBinary(40, 2, addition));
    System.out.println("20 - 10 = " +
        myApp.operateBinary(20, 10, subtraction));    
}

}

The method operateBinary performs a mathematical operation on two integer operands. The operation itself is specified by an instance of IntegerMath. The example defines two operations with lambda expressions, addition and subtraction. The example prints the following:

40 + 2 = 42
20 - 10 = 10

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值