引子
将行为作为数据通报
奈何在一行代码里同时计较一个列表的和、最大值、最小值、平均值、元素个数、奇偶分组、指数、排序呢?
谜底是思维反转!将行为作为数据通报。 文艺青年的代码如下所示:
public class FunctionUtil { public static <T,R> List<R> multiGetResult(List<Function<List<T>, R>> functions, List<T> list) { return functions.stream().map(f -> f.apply(list)).collect(Collectors.toList()); } public static void main(String[] args) { System.out.println(multiGetResult( Arrays.asList( list -> list.stream().collect(Collectors.summarizingInt(x->x)), list -> list.stream().filter(x -> x < 50).sorted().collect(Collectors.toList()), list -> list.stream().collect(Collectors.groupingBy(x->(x%2==0? "even": "odd"))), list -> list.stream().sorted().collect(Collectors.toList()), list -> list.stream().sorted().map(Math::sqrt).collect(Collectors.toMap(x->x, y->Math.pow(2,y)))), Arrays.asList(64,49,25,16,9,4,1,81,36))); } }
呃,有点矫饰小智慧。 不外要是能将行为作为数据自由通报和施加于数据集发生功效,那么其代码表达本领将如庄子之言,尽情潇洒而无所极限。病毒,不就是将行为匿身于数据中的一种表示么?
行为就是数据。
java8函数框架解读">Java8函数框架解读
函数编程的最直接的表示,莫过于将函数作为数据自由通报,团结泛型推导本领,使代码表达本领得到飞一般的晋升。那么,Java8是怎么支持函数编程的呢?主要有三个焦点观念:
函数接口
关于函数接口,需要记着的就是两件事:
最直接的支持就是 java.util.Function 包。界说了四个最基本的函数接口:
个中, compose, andThen, and, or, negate 用来组合函数接口而获得更强大的函数接口。
其它的函数接口都是通过这四个扩展而来。
那么,这些函数接口可以吸收哪些值呢?
在博文“利用函数接口和列举实现设置式编程(Java与Scala实现)”, “简练代码:一次Java函数式编程的重构之旅” 给出了根基的例子。后头尚有更多例子。重在本身操练和实验。
聚合器
先说聚合器。每一个流式计较的末端总有一个雷同 collect(Collectors.toList()) 的要领挪用。collect 是 Stream 的要领,而参数则是聚合器Collector。已有的聚合器界说在Collectors 的静态要领里。 那么这个聚合器是怎么实现的呢?
大部门聚合器都是基于 Reduce 操纵实现的。 Reduce ,名曰推导,含有三个要素: 初始值 init, 二元操纵符 BinaryOperator, 以及一个用于聚合功效的数据源S。
Reduce 的算法如下:
STEP1: 初始化功效 R = init ;
STEP2: 每次从 S 中取出一个值 v,通过二元操纵符施加到 R 和 v ,发生一个新值赋给 R = BinaryOperator(R, v);反复 STEP2, 直到 S 中没有值可取为止。
好比一个列表求和,Sum([1,2,3]) , 那么界说一个初始值 0 以及一个二元加法操纵 BO = a + b ,通过三步完成 Reduce 操纵:step1: R = 0; step2: v=1, R = 0+v = 1; step2: v=2, R = 1 + v = 3 ; step3: v = 3, R = 3 + v = 6。