一,接口的默认方法
java8通过使用default关键字向接口添加非抽象方法实现,此功能也称为虚拟扩展方法。
二,Lambda表达式
1,函数式接口
指仅包含一个抽象方法,但可以有多个非抽象方法(默认方法)的接口。
Lamda表达式:匿名函数,一段可以传递的代码。
可以使代码量减少:
import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.TreeSet; import org.junit.Test; public class testLambda{ //匿名内部类 @Test public void test1() { Comparator<Integer> com = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { // TODO Auto-generated method stub return Integer.compare(o1, o2); } }; TreeSet<Integer> ts = new TreeSet<>(com); } //Lambda表达式 public void test2() { Comparator<Integer> com = (x,y) -> Integer.compare(x, y); TreeSet<Integer> ts = new TreeSet<>(com); }
实例:根据不同信息筛选当前员工资料。
创建员工类:
public class Employee { private String name; private int age; private double salary; /** * @param name * @param age * @param salary */ public Employee(String name, int age, double salary) { super(); this.name = name; this.age = age; this.salary = salary; } public Employee() { super(); // TODO Auto-generated constructor stub } /** * Get name. * @return the name */ public String getName() { return name; } /** * Set the name. * @param name the name to set */ public void setName(String name) { this.name = name; } /** * Get age. * @return the age */ public int getAge() { return age; } /** * Set the age. * @param age the age to set */ public void setAge(int age) { this.age = age; } /** * Get salary. * @return the salary */ public double getSalary() { return salary; } /** * Set the salary. * @param salary the salary to set */ public void setSalary(double salary) { this.salary = salary; } }
员工信息:
List<Employee> employee = Arrays.asList( new Employee("张三", 18, 8000), new Employee("李四", 50, 10000), new Employee("王五", 45, 20000), new Employee("赵六", 19, 7500) );
筛选年龄大于35岁的员工:
@Test public void test3() { List<Employee> list = filterEmployees(employee); for(Employee employee : list) { System.out.println(employee); } } public List<Employee> filterEmployees(List<Employee> List){ List<Employee> emps = new ArrayList<>(); for(Employee emp : emps) { if(emp.getAge() >= 35) { emps.add(emp); } } return emps; }
但这样每有一个新需求就要写一个新方法,过于繁琐。
优化方法一:策略设计模式
创建泛型接口MyPredicate:
public interface MyPredicate<T>{ public boolean test(T t); }
创建FilterEmployeeByAge类继承MyPredicate接口,重写方法通过年龄筛选员工,根据其他信息筛选时只需再新建一个类继承MyPredicate:
public class FilterEmployeeByAge implements MyPredicate<Employee>{ @Override public boolean test(Employee t) { return t.getAge() >= 35; } }
只用写一个方法,通过创建类来实现接口:
@Test public void test4() { //通过年龄筛选 List<Employee> list = filterEmployee(employee, new FilterEmployeeByAge()); for(Employee employee : list) { System.out.println(employee); } //通过工资筛选 List<Employee> list2 = filterEmployee(employee, new FilterEmployeeBySalary()); for(Employee employee : list2) { System.out.println(employee); } } //只用写一个方法,只用创建类来实现接口 public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> mp){ List<Employee> emps = new ArrayList<>(); for(Employee employee: list) { if(mp.test(employee)) { emps.add(employee); } } return emps; }
这种方法虽然只用写一个方法,但要新建多个类来实现不同需求,还是很麻烦
优化方法二:匿名内部类
//优化方法2:匿名内部类 @Test public void test5() { List<Employee> list = filterEmployee(employee, new MyPredicate<Employee>(){ @Override public boolean test(Employee t) { return t.getSalary() <= 5000; } }); for(Employee employee : list) { System.out.println(employee); } }
这种方法可读性较差
优化方法三:Lambda表达式
//优化方法3:Lambda表达式 public void test6() { List<Employee> list = filterEmployee(employee, (e) -> e.getSalary() <= 5000); list.forEach(System.out::println); }
优化方法四:Stream API
//优化方式4:Stream API @Test public void test7() { employee.stream() .filter((e) -> e.getSalary() >= 5000) .limit(2) .forEach(System.out::println); }