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