Java8——初探函数式接口
2018-02-28 14:37
295 查看
这里我们来以筛选苹果举例,如何逐步优化代码,实现函数式编程。
首先,我们的第一个方案可能是下面这样的:
上面代码对绿色的苹果进行过滤,如果我们想根据其他颜色进行过滤,我们可以将颜色作为参数进行传递,代码如下:
以上代码实现了根据苹果的颜色进行筛选,但是当需求更改需要根据苹果重量进行筛选之后怎么办呢?在以前肯定是再写一个方法,通过重量进行筛选,但是这样也就形成了代码重复,显得笨拙。
让我们来看一下更高层次的抽象。一种可能的解决方案是对你的选择标准建模:你考虑的是苹果,需要根据Apple的某些属性来返回一个boolean值。我们把它称为谓词(即返回boolean值的函数),让我们定义一个接口来对选择标准建模,代码如下:
ApplePredicate接口类:
实现该接口之后编写具体的过滤条件,你可以把这些标准看做filter方法的不同行为
以上通过通过不同的策略模式来进行筛选,但是这样也存在问题,每个新的筛选条件都需要实现一次接口,显得繁琐,该怎么只利用ApplePredicate来实现不同的实现呢?你需要filterApples方法接受ApplePredicate对象,对Apple做条件测试。这就是行为参数化:让方法接受多种行为作为参数,并在内部使用,来完成不同的行为。
在这里给filterApples方法添加一个参数,让他接受ApplePredicate对象,代码如下:
在这里一种方式是通过匿名类实现ApplePredicate对象,重写筛选的例子实现过滤:
但是我们可以通过更简单的方式实现筛选,通过filterApples(inventory, (apple -> apple.getWeight() < 150))使用。
如此便实现了一个参数多种行为,我们可以通过传递不同的行为打到不同的目的。
对于上面的函数还可以更进一步抽象化,引入泛型,将list的参数抽象化
以上便是使用函数式接口的一个简单例子。
首先,我们的第一个方案可能是下面这样的:
public static List<Apple> filterGreenApples(List<Apple> inventory) { List<Apple> result = new ArrayList<Apple>(); for(Apple apple: inventory){ if( "green".equals(apple.getColor() ) { result.add(apple); } } return result; }
上面代码对绿色的苹果进行过滤,如果我们想根据其他颜色进行过滤,我们可以将颜色作为参数进行传递,代码如下:
public static List<Apple> filterApplesByColor(List<Apple> inventory, String color) { List<Apple> result = new ArrayList<Apple>(); for (Apple apple: inventory){ if ( apple.getColor().equals(color) ) { result.add(apple); } } return result; }
以上代码实现了根据苹果的颜色进行筛选,但是当需求更改需要根据苹果重量进行筛选之后怎么办呢?在以前肯定是再写一个方法,通过重量进行筛选,但是这样也就形成了代码重复,显得笨拙。
让我们来看一下更高层次的抽象。一种可能的解决方案是对你的选择标准建模:你考虑的是苹果,需要根据Apple的某些属性来返回一个boolean值。我们把它称为谓词(即返回boolean值的函数),让我们定义一个接口来对选择标准建模,代码如下:
ApplePredicate接口类:
public interface ApplePredicate { boolean test(Apple apple); }
实现该接口之后编写具体的过滤条件,你可以把这些标准看做filter方法的不同行为
public class AppleHeaveWeightPredicate implements ApplePredicate { @Override public boolean test(Apple apple) { return apple.getWeight() > 150; } } public class AppleGreenColorPredicate implements ApplePredicate { @Override public boolean test(Apple apple) { return "green".equals(apple.getColor()); } }
以上通过通过不同的策略模式来进行筛选,但是这样也存在问题,每个新的筛选条件都需要实现一次接口,显得繁琐,该怎么只利用ApplePredicate来实现不同的实现呢?你需要filterApples方法接受ApplePredicate对象,对Apple做条件测试。这就是行为参数化:让方法接受多种行为作为参数,并在内部使用,来完成不同的行为。
在这里给filterApples方法添加一个参数,让他接受ApplePredicate对象,代码如下:
public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p ){ List<Apple> result = new ArrayList<>(); for(Apple apple : inventory) { if(p.test(apple)) //谓词对象封装了测试苹果的条件 System.out.println(apple.toString()); result.add(apple); } return result; }
在这里一种方式是通过匿名类实现ApplePredicate对象,重写筛选的例子实现过滤:
List<Apple> redApples = filterApples(inventory, new ApplePredicate() { public boolean test(Apple apple){ return "red".equals(apple.getColor()); } });
但是我们可以通过更简单的方式实现筛选,通过filterApples(inventory, (apple -> apple.getWeight() < 150))使用。
如此便实现了一个参数多种行为,我们可以通过传递不同的行为打到不同的目的。
对于上面的函数还可以更进一步抽象化,引入泛型,将list的参数抽象化
public static <T> List<T> filter(List<T> list, Predicate<T> p) {//这里使用了Java8提供的Predicate方法 List<T> result = new ArrayList<T>(); for(T e : list) { if(p.test(e)) { result.add(e); } } return result; }
以上便是使用函数式接口的一个简单例子。
相关文章推荐
- java8学习之BiFunction函数式接口实例演示&Predicate函数式接口详解
- [Java] 【源码】新手初探java网络编程——socket接口实现简单的客户机/服务器程序
- JAVA 函数式接口与c#委托对应关系(一)
- java 8之函数式接口
- Java8中内置的四大核心函数式接口
- Java 8 函数式接口、lambda表达式、方法以及构造器引用
- java8新增特性(二)----函数式接口(Functional)
- java学习:java8新特性之一,函数式接口
- Rhyme/Java 8 四大核心函数式接口
- 实例详解Java8函数式接口
- Function接口 – Java8中java.util.function包下的函数式接口
- Java 8 Function函数式接口及函数式接口实例
- [java8] lambda表达式、函数式接口和方法引用
- Lambda&Java多核编程-5-函数式接口与function包
- java 8 内置四大核心函数式接口
- Java8自定义带泛型的函数式接口
- java8 内置的四大核心函数式接口
- java8 四个函数式接口
- 必看:深入学习Java8中的函数式接口