您当前的位置: 首页 > 

Dongguo丶

暂无认证

  • 1浏览

    0关注

    472博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Lambda表达式初探

Dongguo丶 发布时间:2018-08-04 21:05:08 ,浏览量:1

Lambda表达式的本质只是一个"语法糖",由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能,Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递),可以写出更简洁、更灵活的代码。

Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。 Lambda表达式还增强了集合库。 Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了许多额外的功能。 总的来说,lambda表达式和 stream 是自Java语言添加泛型(Generics)和注解(annotation)以来最大的变化。

替代匿名内部类

毫无疑问,lambda表达式用得最多的场合就是替代匿名内部类

实例1:实现Runnable方式创建线程

@Test
public void test4() throws Exception {
    //使用匿名内部类:
    new Thread(new Runnable() {
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }).start();
    //用Lambda表达式
    new Thread(() -> System.out.println(Thread.currentThread().getName())).start();
    Thread.currentThread().join();
}

以上两种实现方式的代码执行效果完全一样,但是Lambda表达式却更加简洁,使得原本很多代码的写法变得更加洁、  优雅。

实例2:使用Comparator比较两个数字的大小

@Test
public void test3() {
    //匿名内部类
    Comparator comparator1 = new Comparator() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1.compareTo(o2);
        }
    };
    //lambda
    Comparator comparator2 = (o1, o2) -> o1.compareTo(o2);
}
使用lambda表达式对集合进行迭代

Java的集合类是日常开发中经常用到的,甚至说没有哪个java代码中没有使用到集合类。。。而对集合类最常见的操作就是进行迭代遍历了。请看对比:

    @Test
    public void iterTest() {
        List languages = Arrays.asList("java","scala","python");
        //before java8
        for(String each:languages) {
            System.out.println(each);
        }
        //after java8
        languages.forEach(x -> System.out.println(x));
        languages.forEach(System.out::println);
    }

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

在软件工程中,一个众所周知的问题就是,不管你做什么,用户的需求肯定会变。比方说对于员工信息进行查询

那么首先创建一个员工Employee类。

package com.dongguo.java8.employee;

/**
 * @author Dongguo
 * @date 2021/8/14 0014-15:00
 * @description:
 */
public class Employee {
     private String name;
    private int age;
    private long salary;

    public Employee() {
    }

    public Employee(String name, int age, long salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public long getSalary() {
        return salary;
    }

    public void setSalary(long salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }
}

需求1:获得当前公司员工年龄大于35的员工信息

package com.dongguo.java8.lambda;

import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author Dongguo
 * @date 2021/8/14 0014-15:02
 * @description:
 */
public class EmployeeDemo {
    //创建一个员工集合
    List employees = Arrays.asList(new Employee("张三", 18, 3000),
            new Employee("张三", 18, 4000),
            new Employee("李四", 28, 5000),
            new Employee("王五", 38, 6000),
            new Employee("赵六", 48, 5500),
            new Employee("田七", 58, 4500));

    @Test
    public void test1() {
        List list = filterEmployeeByAge(employees);
        System.out.println(list);
    }

    /**
     * @author Dongguo
     * @date 2021/8/14 0014 15:15
     * @description:获得当前公司员工年龄大于35的员工信息
     */
    public static List filterEmployeeByAge(List list) {
        List emps = new ArrayList();
        for (Employee emp : list) {
            if (emp.getAge() > 35) {
                emps.add(emp);
            }
        }
        return emps;
    }
}

运行结果:
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}, Employee{name='田七', age=58, salary=4500}]

需求更改

需求2:获取当前公司员工工资大于5000的员工信息

package com.dongguo.java8.lambda;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author Dongguo
 * @date 2021/8/14 0014-15:02
 * @description:
 */
public class EmployeeDemo {
    //创建一个员工集合
    List employees = Arrays.asList(new Employee("张三", 18, 3000),
            new Employee("张三", 18, 4000),
            new Employee("李四", 28, 5000),
            new Employee("王五", 38, 6000),
            new Employee("赵六", 48, 5500),
            new Employee("田七", 58, 4500));
    @Test
    public void test2() {
        List list = filterEmployeeByAge(employees);
        System.out.println(list);
    }

    /**
     * @author Dongguo
     * @date 2021/8/14 0014 15:19
     * @description:需求:获取当前公司员工工资大于5000的员工信息
     */
    public static List filterEmployeeBySalary(List list) {
        List emps = new ArrayList();
        for (Employee emp : list) {
            if (emp.getSalary() > 5000) {
                emps.add(emp);
            }
        }
        return emps;
    }
}
运行结果:
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}, Employee{name='田七', age=58, salary=4500}]

这是最容易 想到的方法,很显然根据不同条件获取信息,产生了过多的冗余代码,现在我们想办法对代码进行优化

优化1:

提取一个接口 ,提供一个公共方法

子类通过重写方法实现自己的判断

只需要通过一个方法就可以判断不同条件的过滤 ---采用策略模式

首先创建一个接口

package com.dongguo.java8.employee;

/**
 * @author Dongguo
 * @date 2021/8/14 0014-15:21
 * @description:
 */
public interface MyPredicate {
    public boolean predicate(T t);
}

创建两个实现类

package com.dongguo.java8.employee;

/**
 * @author Dongguo
 * @date 2021/8/14 0014-15:29
 * @description:
 */
public class FilterEmployeeByAge implements MyPredicate {
    @Override
    public boolean predicate(Employee e) {
        return e.getAge() > 35;
    }
}
package com.dongguo.java8.employee;

/**
 * @author Dongguo
 * @date 2021/8/14 0014-15:30
 * @description:
 */
public class FilterEmployeeBySalary implements MyPredicate {
    @Override
    public boolean predicate(Employee employee) {
        return employee.getSalary() > 5000;
    }
}
package com.dongguo.java8.lambda;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author Dongguo
 * @date 2021/8/14 0014-15:02
 * @description:
 */
public class EmployeeDemo {
    //创建一个员工集合
    List employees = Arrays.asList(new Employee("张三", 18, 3000),
            new Employee("张三", 18, 4000),
            new Employee("李四", 28, 5000),
            new Employee("王五", 38, 6000),
            new Employee("赵六", 48, 5500),
            new Employee("田七", 58, 4500));


    @Test
    public void test3() {
        //获得当前公司员工年龄大于35的员工信息
        List list = filterEmployee(employees,new FilterEmployeeByAge());
        System.out.println(list);
        //获取当前公司员工工资大于5000的员工信息
        List list2 = filterEmployee(employees,new FilterEmployeeBySalary());
        System.out.println(list2);
    }

    /**
     * @author Dongguo
     * @date 2021/8/14 0014 15:33
     * @description:根据不同的条件过滤
     */
    public static  List filterEmployee( List list ,MyPredicate p){
        List emps = new ArrayList();
        for (Employee emp:list) {
            if (p.predicate(emp)){
                emps.add(emp);
            }
        }
        return emps;
    }
}
运行结果:
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}, Employee{name='田七', age=58, salary=4500}]
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}]

对代码优化最好的方式就是设计模式,现在有一个通用的过滤方法,如果再有其他过滤条件只需要添加一个实现MyPredicate接口的实现类就可以了,之前的代码都不需要修改,但是每添加一个过滤条件就要新创建一个实现类,也是非常麻烦的。

优化二:只通过提供的接口 使用匿名内部类自己去实现具体的判断

package com.dongguo.java8.lambda;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author Dongguo
 * @date 2021/8/14 0014-15:02
 * @description:
 */
public class EmployeeDemo {
    //创建一个员工集合
    List employees = Arrays.asList(new Employee("张三", 18, 3000),
            new Employee("张三", 18, 4000),
            new Employee("李四", 28, 5000),
            new Employee("王五", 38, 6000),
            new Employee("赵六", 48, 5500),
            new Employee("田七", 58, 4500));
    
    /**
     * @author Dongguo
     * @date 2021/8/14 0014 15:33
     * @description:根据不同的条件过滤
     */
    public static  List filterEmployee( List list ,MyPredicate p){
        List emps = new ArrayList();
        for (Employee emp:list) {
            if (p.predicate(emp)){
                emps.add(emp);
            }
        }
        return emps;
    }

    @Test
    public void test4() {
        //获得当前公司员工年龄大于35的员工信息
        List list = filterEmployee(employees, new MyPredicate() {
            @Override
            public boolean predicate(Employee employee) {
                return employee.getAge() > 35;
            }
        });
        System.out.println(list);
        //获取当前公司员工工资大于5000的员工信息
        List list2 = filterEmployee(employees, new MyPredicate() {
            @Override
            public boolean predicate(Employee employee) {
                return employee.getSalary()>5000;
            }
        });
        System.out.println(list2);
    } 
}
运行结果:
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}, Employee{name='田七', age=58, salary=4500}]
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}]

使用匿名内部类同样能够实现,但是在之前就说过lambda表达式可以替代匿名内部类

优化三:lambda表达式

package com.dongguo.java8.lambda;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author Dongguo
 * @date 2021/8/15 0015-15:33
 * @description:
 */
public class TestLambda {


    List employees = Arrays.asList(new Employee("张三", 18, 3000),
            new Employee("张三", 18, 4000),
            new Employee("李四", 28, 5000),
            new Employee("王五", 38, 6000),
            new Employee("赵六", 48, 5500),
            new Employee("田七", 58, 4500));

    @Test
    public void test1() {
        //获得当前公司员工年龄大于35的员工信息
        List list = filterEmployee(employees, (employee) -> employee.getAge() > 35);
        System.out.println(list);
        //获取当前公司员工工资大于5000的员工信息
        List list2 = filterEmployee(employees, (employee) -> employee.getSalary() > 5000);
        System.out.println(list2);
    }
    /**
     * @author Dongguo
     * @date 2021/8/14 0014 15:33
     * @description:根据不同的条件过滤
     */
    public static List filterEmployee(List list, MyPredicate p) {
        List emps = new ArrayList();
        for (Employee emp : list) {
            if (p.predicate(emp)) {
                emps.add(emp);
            }
        }
        return emps;
    }
}
运行结果
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}, Employee{name='田七', age=58, salary=4500}]
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}]

这样成功的从匿名内部类到Lambda表达式的使用

优化四:Stream API

Stream是对集合的包装,通常和lambda一起使用。让我们看下是如何使用

package com.dongguo.java8.lambda;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author Dongguo
 * @date 2021/8/15 0015-15:33
 * @description:
 */
public class TestLambda {

    List employees = Arrays.asList(new Employee("张三", 18, 3000),
            new Employee("张三", 18, 4000),
            new Employee("李四", 28, 5000),
            new Employee("王五", 38, 6000),
            new Employee("赵六", 48, 5500),
            new Employee("田七", 58, 4500));
    @Test
    public void test2() {
        //获得当前公司员工年龄大于35的员工信息
        employees.stream().filter(employee -> (employee.getAge() > 35)).forEach(System.out::println);
        System.out.println("-------------------------------------");
        //获取当前公司员工工资大于5000的员工信息
        employees.stream().filter(employee -> (employee.getSalary() > 5000)).forEach(System.out::println);
    }
}
运行结果:
Employee{name='王五', age=38, salary=6000}
Employee{name='赵六', age=48, salary=5500}
Employee{name='田七', age=58, salary=4500}
-------------------------------------
Employee{name='王五', age=38, salary=6000}
Employee{name='赵六', age=48, salary=5500}

这样最终我们的代码可以完成如此的精简,真是美好的体验。

关注
打赏
1638062488
查看更多评论
立即登录/注册

微信扫码登录

0.0398s