资讯专栏INFORMATION COLUMN

Java 8 新特性之Lambda表达式

Ververica / 3095人阅读

摘要:概述简介是一个匿名函数,我们可以把表达式理解为是一段可以传递的代码将代码像数据一样进行传递。作为一种更紧凑的代码风格,使的语言表达能力得到了提升。任何满足单一抽象方法法则的接口,都会被自动视为函数接口。

1. 概述 1.1 简介

Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使 Java 的语言表达能力得到了提升。

1.2 为什么要使用 Lambda 表达式 1. 实例

比如说我们要为 TreeSet 添加一个比价器,如果用原来的匿名内部类实现如下

@Test
public void test1() {
    Comparator com = new Comparator() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return Integer.compare(o1, o2);
        }
    };

    TreeSet ts = new TreeSet<>(com);

    TreeSet ts2 = new TreeSet<>(new Comparator() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return Integer.compare(o1, o2);
        }
    });

    ts2.addAll(Arrays.asList(4, 5, 7, 3, 2, 1, 8, 6, 9));
    System.out.println(ts2.toString());
}

Lambda 表达式实现如下

@Test
public void test2() {
    Comparator com = (x, y) -> Integer.compare(x, y);
    TreeSet ts = new TreeSet<>(com);
    ts.addAll(Arrays.asList(4, 5, 7, 3, 2, 1, 8, 6, 9));
    System.out.println(ts.toString());
}
2. 实例

对一个 List 里面的对象进行操作

实体类

public class Employee implements Serializable {

    private int id;
    private String name;
    private int age;
    private double salary;
    
    // 省略 getter 和 setter 方法
}

基础数据

List emps = Arrays.asList(
        new Employee(1, "张三", 18, 9999.99),
        new Employee(2, "李四", 59, 6666.66),
        new Employee(3, "王五", 28, 3333.33),
        new Employee(4, "赵六", 8, 7777.77),
        new Employee(5, "田七", 38, 5555.55)
);
普通实现

我们有两个需求,一个是“获取公司中年龄小于 35 的员工信息”,一个是“获取公司中工资大于 5000 的员工信息”

/**
 * 需求:获取公司中年龄小于 35 的员工信息
 *
 * @param emps
 * @return
 */
public List filterEmployeeAge(List emps) {
    List list = new ArrayList<>();
    for (Employee emp : emps) {
        if (emp.getAge() <= 35) {
            list.add(emp);
        }
    }
    return list;
}

@Test
public void test3() {
    List list = filterEmployeeAge(emps);

    for (Employee employee : list) {
        System.out.println(employee);
    }
}

/**
 * 需求:获取公司中工资大于 5000 的员工信息
 *
 * @param emps
 * @return
 */
public List filterEmployeeSalary(List emps) {
    List list = new ArrayList<>();
    for (Employee emp : emps) {
        if (emp.getSalary() >= 5000) {
            list.add(emp);
        }
    }
    return list;
}

这样的话我要神队每个需求都写个方法,如果再增加需求,还需要再写

优化方式一:策略设计模式

定义一个接口

public interface MyPredicate {

    public boolean test(T t);
    
}
/**
 * 策略设计模式
 *
 * @param emps
 * @param mp
 * @return
 */
public List filterEmployee(List emps, MyPredicate mp) {
    List list = new ArrayList<>();
    for (Employee employee : emps) {
        if (mp.test(employee)) {
            list.add(employee);
        }
    }
    return list;
}

/**
 * 根据不同的需求实现不同的策略
 */
@Test
public void test4() {
    List list = filterEmployee(emps, new FilterEmployeeForAge());
    for (Employee employee : list) {
        System.out.println(employee);
    }

    System.out.println("---------------------------------------");

    List list2 = filterEmployee(emps, new FilterEmployeeForSalary());
    for (Employee employee : list2) {
        System.out.println(employee);
    }
}
优化方式二:匿名内部类
/**
 * 匿名内部类
 */
@Test
public void test5() {
    List list = filterEmployee(emps, new MyPredicate() {
        @Override
        public boolean test(Employee t) {
            return t.getId() <= 103;
        }
    });

    for (Employee employee : list) {
        System.out.println(employee);
    }
}
优化方式三:Lambda 表达式
/**
 * Lambda 表达式
 */
@Test
public void test6() {
    List list = filterEmployee(emps, (e) -> e.getAge() <= 35);
    list.forEach(System.out::println);

    System.out.println("------------------------------------------");

    List list2 = filterEmployee(emps, (e) -> e.getSalary() >= 5000);
    list2.forEach(System.out::println);
}
优化方式四:Stream API
/**
 * Stream API
 */
@Test
public void test7() {
    emps.stream()
            .filter((e) -> e.getAge() <= 35)
            .forEach(System.out::println);

    System.out.println("----------------------------------------------");

    emps.stream()
            .map(Employee::getName)
            .limit(3)
            .sorted()
            .forEach(System.out::println);
}
2. Lambda 表达式的基础语法

Java8 中引入了一个新的操作符 -> 该操作符称为箭头操作符或 Lambda 操作符,箭头操作符将 Lambda 表达式拆分成两部分:

左侧:Lambda 表达式的参数列表(即接口抽象方法的参数列表)

右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体(即接口的实现)

Lambda 表达式需要“函数式接口”的支持

函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。可以使用注解 @FunctionalInterface 修饰,可以检查是否是函数式接口

函数式接口可以有默认方法和静态方法。

任何满足单一抽象方法法则的接口,都会被自动视为函数接口。这包括 Runnable 和 Callable 等传统接口,以及您自己构建的自定义接口。

2.1 无参数,无返回值
() -> System.out.println("Hello Lambda!");
1. 实例
@Test
public void t1(){
    Runnable r1 = () -> System.out.println("Hello Lambda!");
    r1.run();
}
2.2 有一个参数,并且无返回值
(x) -> System.out.println(x)
1. 实例
@Test
public void t2(){
    Consumer con = (x) -> System.out.println(x);
    con.accept("Hello Lambda!");
}
2. 实例

如果只有一个参数的情况下小括号是可以省略的

@Test
public void t3(){
    Consumer con = x -> System.out.println(x);
    con.accept("Hello Lambda!");
}
2.3 有两个以上的参数,有返回值,并且 Lambda 体中有多条语句 1. 实例
@Test
public void t4() {
    Comparator com = (x, y) -> {
        System.out.println("函数式接口");
        return Integer.compare(x, y);
    };
}
2.4 若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写 1. 实例
@Test
public void t5(){
    Comparator com = (x, y) -> Integer.compare(x, y);
}

Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”,如果写类型的话如下

@Test
public void t6(){
    Comparator com = (Integer x,Integer y) -> Integer.compare(x, y);
}
本文首发于凌风博客:Java 8 新特性之Lambda表达式
作者:凌风

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72743.html

相关文章

  • Java 8 特性方法引用

    摘要:概述简介若体中的功能,已经有方法提供了实现,可以使用方法引用可以将方法引用理解为表达式的另外一种表现形式方法引用的三种形式对象的引用实例方法名类名静态方法名类名实例方法名注意方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象 1. 概述 1.1 简介 若 Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用(可以将方法引用理解为 Lambda 表达式的另外一...

    wudengzan 评论0 收藏0
  • Java8特性Lambda达式

    摘要:表达式说白了就是一种匿名方法,不需要方法名,修饰符,和返回值类型。就目前而言表达式只能简化接口的匿名内部类实现。 Lambda表达式说白了就是一种匿名方法,不需要方法名,修饰符,和返回值类型。 使用方法 首先在moudle的build.gradle文件中添加配置:app/build.gradle添加。 android { ... defaultConfi...

    mist14 评论0 收藏0
  • Java8 lambda 达式、方法引用、函数式接口、默认方式、静态方法

    摘要:欧阳思海继承接口后,又加了新的抽象方法,这个接口就不再是函数式接口默认方法在接口中添加了一个默认方法。总结在这篇文章中,我们讲了表达式方法引用函数式接口接口中的静态方法接口中的默认方法的使用。 今天我来聊聊 Java8 的一些新的特性,确实 Java8 的新特性的出现,给开发者带来了非常大的便利,可能刚刚开始的时候会有点不习惯的这种写法,但是,当你真正的熟悉了之后,你一定会爱上这些新的...

    isLishude 评论0 收藏0
  • 深入浅出 Java 8 Lambda 达式

    摘要:在支持一类函数的语言中,表达式的类型将是函数。匿名函数的返回类型与该主体表达式一致如果表达式的主体包含一条以上语句,则表达式必须包含在花括号中形成代码块。注意,使用表达式的方法不止一种。 摘要:此篇文章主要介绍 Java8 Lambda 表达式产生的背景和用法,以及 Lambda 表达式与匿名类的不同等。本文系 OneAPM 工程师编译整理。 Java 是一流的面向对象语言,除了部分简...

    wdzgege 评论0 收藏0
  • 乐字节Java8核心特性实战方法引用

    摘要:大家好,我是乐字节的小乐,上一次我们说到了核心特性之函数式接口,接下来我们继续了解又一核心特性方法引用。方法引用是一种更简洁易懂的表达式。感谢光临阅读小乐的,敬请关注乐字节后续将继续讲述等前沿知识技术。 大家好,我是乐字节的小乐,上一次我们说到了Java8核心特性之函数式接口,接下来我们继续了解Java8又一核心特性——方法引用。 showImg(https://segmentfaul...

    lakeside 评论0 收藏0

发表评论

0条评论

Ververica

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<