Java 8之前,参数只能是基本类型或对象引用。Java 8出现后,方法作为参数变得现实,也即函数式编程。
案例:果园大叔家的苹果熟了,收割后全装到一个箱子里了,现在要对苹果进行分类,将红苹果和绿苹果分开,将大苹果(重量大于等于150g)与小苹果(重量小于150g)分开。
尝试1: 传统思路
import java.util.ArrayList;
import java.util.List;
public class Apple {
Color color;
int weight;
Apple(Color color, int w) {
this.color=color;
this.weight=w;
}
public static List<Apple> filterGreenApples(List<Apple> list) {
List<Apple> res=new ArrayList<>();
for(Apple apple: list) {
if(Color.GREEN.equals(apple.color)) {
res.add(apple);
}
}
return res;
}
public static List<Apple> filterBigApples(List<Apple> list) {
List<Apple> res=new ArrayList<>();
for(Apple apple: list) {
if(apple.weight>=150) {
res.add(apple);
}
}
return res;
}
}
enum Color {
GREEN, RED
}
点评:能解决果园大叔的需求,但是仅一个条件不同(一行代码),就要复制粘贴,重新再写一个方法。如果农民大叔想要区分“大的且绿的苹果”,“小的且红的苹果”等,就需要重新写一个方法了。
差评*****:代码冗长,不能应对需求变更。
尝试2:将条件抽象成一个方法,使用策略设计模式
import java.util.ArrayList;
import java.util.List;
public class Apple2 {
public static List<Apple> filterApple(List<Apple> list, FilterApple filterApple) {
List<Apple> res=new ArrayList<>();
for(Apple apple: list) {
if(filterApple.test(apple)) {
res.add(apple);
}
}
return res;
}
}
interface FilterApple {
boolean test(Apple apple);
}
class GreenAppleFilter implements FilterApple {
@Override
public boolean test(Apple apple) {
return Color.GREEN.equals(apple.color);
}
}
class BigAppleFilter implements FilterApple {
@Override
public boolean test(Apple apple) {
return Color.GREEN.equals(apple.color);
}
}
点评:每有一个新条件,只需要创建AppleFilter的实现类,然后将该对象传入即可,能够应对需求变化。
中评***:能够应对需求变化,但是代码啰嗦冗长,每次都要新建一个类。
尝试3:匿名内部类
import java.util.ArrayList;
import java.util.List;
public class Apple3 {
public static List<Apple> filterApple(List<Apple> list, FilterApple filterApple) {
List<Apple> res=new ArrayList<>();
for(Apple apple: list) {
if(filterApple.test(apple)) {
res.add(apple);
}
}
return res;
}
public static void main(String[] args) {
List<Apple> list=new ArrayList<>();
list.add(new Apple(Color.GREEN,140));
list.add(new Apple(Color.GREEN,160));
list.add(new Apple(Color.GREEN,180));
list.add(new Apple(Color.GREEN,120));
list.add(new Apple(Color.GREEN,170));
list.add(new Apple(Color.GREEN,110));
list.add(new Apple(Color.RED,140));
list.add(new Apple(Color.RED,160));
list.add(new Apple(Color.RED,180));
list.add(new Apple(Color.RED,120));
list.add(new Apple(Color.RED,170));
list.add(new Apple(Color.RED,110));
List<Apple> apples = filterApple(list, new FilterApple() {
@Override
public boolean test(Apple apple) {
return Color.GREEN.equals(apple.color);
}
});
}
}
点评:每用一个条件,直接用匿名内部类创建一个实例传入即可,随用随建,但还有点冗长。
中评***:可以应对需求变化,简单清晰,但有点冗长。
尝试4:使用Lambda表达式
public class Apple4 {
public static void main(String[] args) {
List<Apple> list=new ArrayList<>();
list.add(new Apple(Color.GREEN,140));
list.add(new Apple(Color.GREEN,160));
list.add(new Apple(Color.GREEN,180));
list.add(new Apple(Color.GREEN,120));
list.add(new Apple(Color.GREEN,170));
list.add(new Apple(Color.GREEN,110));
list.add(new Apple(Color.RED,140));
list.add(new Apple(Color.RED,160));
list.add(new Apple(Color.RED,180));
list.add(new Apple(Color.RED,120));
list.add(new Apple(Color.RED,170));
list.add(new Apple(Color.RED,110));
List<Apple> apples = filterApple(list, apple -> Color.GREEN.equals(apple.color));
}
}
点评:直接一行代码传入条件。
好评*****
尝试5:最终抽象,适用于任何情况
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
interface Predicate<T> {
boolean test(T t);
}
public class Apple5 {
public static <T> List<T> filter(List<T> list, Predicate<T> predicate) {
List<T> result=new ArrayList<>();
for(T t: list) {
if(predicate.test(t)) {
result.add(t);
}
}
return result;
}
public static void main(String[] args) {
List<Apple> list=new ArrayList<>();
list.add(new Apple(Color.GREEN,140));
list.add(new Apple(Color.GREEN,160));
list.add(new Apple(Color.GREEN,180));
list.add(new Apple(Color.GREEN,120));
list.add(new Apple(Color.GREEN,170));
list.add(new Apple(Color.GREEN,110));
list.add(new Apple(Color.RED,140));
list.add(new Apple(Color.RED,160));
list.add(new Apple(Color.RED,180));
list.add(new Apple(Color.RED,120));
list.add(new Apple(Color.RED,170));
list.add(new Apple(Color.RED,110));
List<Apple> greenApples = filter(list, apple -> Color.GREEN.equals(apple.color));
System.out.println(greenApples);
List<Apple> bigApples = filter(list, apple -> apple.weight>=150);
System.out.println(bigApples);
List<String> strList= filter(Arrays.asList("hello","holiday","nobody","hi","wendy"),str->str.length()<=5);//过滤出长度小于5的字符串
System.out.println(strList);
List<Integer> integers=filter(Arrays.asList(1,2,3,4,5,7,6,9,8,11,25), i-> (i&1)==0);//过滤偶数
System.out.println(integers);
}
}
可以减少啰嗦代码,应对一切需求变化导致的条件变化。