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);
 }