Java8新特性:Lambda表达式 入门


  • 速度更快
  • 代码更少
  • 强大的Stream 流 API 
  • 便于并行
  • 最大化减少空指针异常

hashmap ======数组+链表+红黑树

永久代---> 元空间

 ====================================================================

Lambda  是一个匿名函数。

=====================================================================

需求1:从员工中找出35岁以上的员工

 需求2:获取工资>5000的员工

需求3:获取年龄<20的员工

.............

员工实体类:

package entity;

public class Employee {
    private String name;
    private Integer age;
    private double money;//工资

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

    public Employee(String name, Integer age, double money) {
        this.name = name;
        this.age = age;
        this.money = money;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
}

需求实现的方法:

   //获取当前公司中员工年龄大于35 的员工信息
    public static List filterEmployees(List list) {
        List employees = new ArrayList<>();
        for (Employee e : list) {
            if (e.getAge() >= 35) {
                employees.add(e);
            }
        }
        return employees;
    }

    //获取当前公司中员工工资大于5000 的员工信息
    public static List filterEmployees1(List list) {
        List employees = new ArrayList<>();
        for (Employee e : list) {
            if (e.getMoney() >= 5000) {
                employees.add(e);
            }
        }
        return employees;
    }
  ........

测试主方法:

 public static void main(String[] args) {
        List employees = Arrays.asList(
                new Employee("aa", 18, 99999.99),
                new Employee("bb", 22, 222222.22),
                new Employee("cc", 33, 23123.9),
                new Employee("dd", 11, 139.99),
                new Employee("ee", 23, 929.99),
                new Employee("ff", 68, 1000.00)
        );

        List result1 = filterEmployees(employees);
        for (Employee e : result1) {
            System.out.println(e);
        }
        System.out.println("======================");
        List result2 = filterEmployees1(employees);
        for (Employee e : result2) {
            System.out.println(e);
        }
    }

运行结果:

发现实现上面几个需求,只需更改  if  中的代码。

代码得优化。

最好的优化方式:设计模式

===============================================================

优化方式一(创建接口,然后提取核心逻辑):

接口:

package editor1;

public interface MyPredicate {

    public boolean test(T t);

}

实现接口:

package editor1;

import entity.Employee;

public class FilterEmployeeByAge implements MyPredicate{
    @Override
    public boolean test(Employee employee) {
        return employee.getAge() >= 35;
    }
}

主方法:

  //优化方式1:
    public static List filterEmployee1(List list, MyPredicate mp){
        List emps = new ArrayList<>();
        for (Employee employee:list){
            if(mp.test(employee)){
                emps.add(employee);
            }
        }
        return emps;
    }



    public static void main(String[] args) {
        List employees = Arrays.asList(
                new Employee("aa", 18, 99999.99),
                new Employee("bb", 22, 222222.22),
                new Employee("cc", 33, 23123.9),
                new Employee("dd", 11, 139.99),
                new Employee("ee", 23, 929.99),
                new Employee("ff", 68, 1000.00)
        );
        List result = filterEmployee1(employees, new FilterEmployeeByAge());
        for (Employee e : result) {
            System.out.println(e);
        }
    }

运行:

但是这也很复杂,加一个需求,就要加一个实现接口的类,看上去和之前是一样的复杂。

这种优化是策略模式。一个接口,不同实现提供不同的需求,达到不同策略的效果。

在之前加一个需求就加一个方法,现在加一个接口。

优化方式二:匿名内部类

接口不变:

package editor1;

public interface MyPredicate {

    public boolean test(T t);

}

  提供调用接口的方法:

  //优化方式2:
    public static List filterEmployee1(List list, MyPredicate mp){
        List emps = new ArrayList<>();
        for (Employee employee:list){
            if(mp.test(employee)){
                emps.add(employee);
            }
        }
        return emps;
    }

  直接在主方法中,用匿名内部类实现 不同需求:

  public static void main(String[] args) {
        List employees = Arrays.asList(
                new Employee("aa", 18, 99999.99),
                new Employee("bb", 22, 222222.22),
                new Employee("cc", 33, 23123.9),
                new Employee("dd", 11, 139.99),
                new Employee("ee", 23, 929.99),
                new Employee("ff", 68, 1000.00)
        );
        List result = filterEmployee1(employees, new MyPredicate() {
            @Override
            public boolean test(Employee employee) {
                return employee.getMoney()<=5000;
            }
        });
        for (Employee e : result) {
            System.out.println(e);
        }
  }

 运行结果:

用匿名内部类和上面类似,也是策略模式,只不过刚才是写了一个实现接口的类,现在直接用匿名内部类了。

可以发现,对于匿名内部类有用的代码 就只有 return那一句。但是为了那一句话,得多写好几行。

所以就Lambda出来。更加简洁。

优化方式三:Lambda表达式

接口不变:

package editor1;

public interface MyPredicate {

    public boolean test(T t);

}

 调用接口的方法也不变:

  public static List filterEmployee1(List list, MyPredicate mp){
        List emps = new ArrayList<>();
        for (Employee employee:list){
            if(mp.test(employee)){
                emps.add(employee);
            }
        }
        return emps;
    }

 主方法有变化,用Lambda表达式:

  public static void main(String[] args) {
        List employees = Arrays.asList(
                new Employee("aa", 18, 99999.99),
                new Employee("bb", 22, 222222.22),
                new Employee("cc", 33, 23123.9),
                new Employee("dd", 11, 139.99),
                new Employee("ee", 23, 929.99),
                new Employee("ff", 68, 1000.00)
        );
        List result = filterEmployee1(employees,(e -> e.getMoney()<=5000));
        for (Employee e : result) {
            System.out.println(e);
        }
  }

运行结果:

 和刚才一样。

这种情况下,加一种需求,只需加一行就ok了。

优化方式四:Strean流式编程

假设现在什么 都没有,只有一个集合,没有接口,也没有调用接口的那个方法,想实现需求怎么做呢?

 public static void main(String[] args) {
        List employees = Arrays.asList(
                new Employee("aa", 18, 99999.99),
                new Employee("bb", 22, 222222.22),
                new Employee("cc", 33, 23123.9),
                new Employee("dd", 11, 139.99),
                new Employee("ee", 23, 929.99),
                new Employee("ff", 68, 1000.00)
        );
        employees.stream()
                .filter((e) -> e.getMoney()<=5000)
                .forEach(System.out::println);
 }

   运行结果:

 和刚才一样。

流式编程很简洁很方便。

在比如,提取出所有名字:

 public static void main(String[] args) {
        List employees = Arrays.asList(
                new Employee("aa", 18, 99999.99),
                new Employee("bb", 22, 222222.22),
                new Employee("cc", 33, 23123.9),
                new Employee("dd", 11, 139.99),
                new Employee("ee", 23, 929.99),
                new Employee("ff", 68, 1000.00)
        );
//        employees.stream()
//                .filter((e) -> e.getMoney()<=5000)
//                .forEach(System.out::println);
        employees.stream()
                .map(Employee::getName)
                .forEach(System.out::println);
 }