Java 8的新增功能相比以往的版本,发生了很大的变化。其中给我们带来的好处是,新功能提供的了强大的新词汇和新设计模式,能帮你编写更清楚、更简洁的代码。学习Java 8,我们要重点学习其中的Lambda表达式,下面的分析也主要根据Lambda来展开。
一、行为参数化的设计模式
我们先来看个例子(参考Java 8 实战):
1)我们帮果农做一个筛选绿苹果的功能,我们很可能是下面这样实现的:
public static List<Apple> filterGreenApples(List<Apple> inventory){
List<Apple> result = new ArrayList<>();//累计苹果的列表
for(Apple apple: inventory){
if("green".equals(apple.getColor())){ //仅仅选出绿苹果
result.add(apple);
}
}
return result;
}
2)然而要是果农想要筛选多种颜色,一种做法是给方法加一个参数,把颜色变成参数,这样就能灵活地适应变化了:
public static List<Apple> filterApplesByColor(List<Apple> inventory, String color){
List<Apple> result = new ArrayList<>();
for(Apple apple: inventory){
if(apple.getColor().equals(color)){
result.add(apple);
}
}
return result;
}
3)突然果农想要做个重量筛选,选出较重的苹果,作为程序员的你一般会想到下面的方法:
public static List<Apple> filterApplesByWeight(List<Apple> inventory, int weight){
List<Apple> result = new ArrayList<>();
for(Apple apple: inventory){
if(apple.getWeight() > weight){
result.add(apple);
}
}
return result;
}
虽然上面的解决方案可以实现功能,但是你复制了大部分的代码来实现遍历库存,并对每个苹果应用筛选条件。这打破了DRY(Don't Repeat Yourself,不用重复自己)的软件工程原则,如果需要改变筛选方式,那就得修改所有的方法实现,这代价太大了。
我们再来看看先的实现方式:
interface ApplePredicate{
public boolean test(Apple a);
}
static class AppleWeightPredicate implements ApplePredicate{
public boolean test(Apple apple){
return apple.getWeight() > 150;
}
}
static class AppleColorPredicate implements ApplePredicate{
public boolean test(Apple apple){
return "green".equals(apple.getColor());
}
}
static class AppleRedAndHeavyPredicate implements ApplePredicate{
public boolean test(Apple apple){
return "red".equals(apple.getColor())
&& apple.getWeight() > 150;
}
}
接着,我们可以这样来使用它
// [Apple{color='green', weight=80}, Apple{color='green', weight=155}]
List<Apple> greenApples2 = filter(inventory, new AppleColorPredicate());
System.out.println(greenApples2);
// [Apple{color='green', weight=155}]
List<Apple> heavyApples = filter(inventory, new AppleWeightPredicate());
System.out.println(heavyApples);
// []
List<Apple> redAndHeavyApples = filter(inventory, new AppleRedAndHeavyPredicate());
System.out.println(redAndHeavyApples);
这就是将行为(函数)作为参数进行传递,这样可以更好地应对不断变化的需求。
上面的代码在Java 8 里可以用Lambda表达式重下为下面的样子:
List<Apple> result = filterApples(inventory, (Apple apple) -> "red".equals(apple.getColors()));
不得不承认这代码看上去比以前的干净了很多。