大多数操作需要一个用户定义的函数。本节列出了指定它们的不同方法。我们还介绍了Accumulators,它可以用来深入了解你的Flink应用程序。
函数实现方式
实现一个接口
最基本的实现就是如下,实现MapFunction接口下map方法。
class MyMapFunction implements MapFunction<String, Integer> {
public Integer map(String value) { return Integer.parseInt(value); }
}
data.map(new MyMapFunction());
匿名类
你可以将函数作为匿名类传递:
data.map(new MapFunction<String, Integer> () {
public Integer map(String value) { return Integer.parseInt(value); }
});
Java 8 Lambdas
Flink还在Java API中支持Java 8 Lambdas。
data.filter(s -> s.startsWith("http://"));
data.reduce((i1,i2) -> i1 + i2);
Rich functions(富函数)
所有需要用户定义函数的转换都可以使用富函数作为参数。
例如,implements MapFunction 可以写成extends RichMapFunction
class MyMapFunction implements MapFunction<String, Integer> {
public Integer map(String value) { return Integer.parseInt(value); }
}
用富函数表示
class MyMapFunction extends RichMapFunction<String, Integer> {
public Integer map(String value) { return Integer.parseInt(value); }
}
## 并像往常一样将该函数传递给映射转换
data.map(new MyMapFunction());
富函数也可以定义为匿名类:
data.map (new RichMapFunction<String, Integer>() {
public Integer map(String value) { return Integer.parseInt(value); }
});
富函数除了提供用户定义的函数(map、reduce等)外,还提供了四种方法:open、close、getRuntimeContext和setRuntimeContext。这对于参数化函数(请参阅向函数传递参数)、创建和终结局部状态、访问广播变量(请参阅广播变量)、访问运行时信息(如累加器和计数器(请参阅累加器和计数器)以及关于迭代的信息(请参阅迭代)都很有用。
累加器和计数器
累加器是带有添加操作和最终累积结果的简单构造,在作业结束后可用。
最简单的累加器是一个计数器:您可以使用累加器增加它。添加(V值)的方法。在作业结束时,Flink将汇总(合并)所有部分结果,并将结果发送给客户端。累加器在调试期间很有用,或者如果你想快速找到更多关于数据的信息。
Flink目前有以下内置的累加器。它们都实现了Accumulator接口:
- IntCounter, LongCounter和DoubleCounter:下面是一个使用计数器的例子。
- Histogram:一个histogram实现的离散数量的箱子。在内部,它只是一个从Integer到Integer的映射。你可以使用它来计算值的分布,例如单词计数程序的每行单词分布。
如何使用累加器:
首先,您必须在用户定义的转换函数中创建一个累加器对象(这里是一个计数器),以便在需要使用它的地方使用它。
private IntCounter numLines = new IntCounter();
其次,必须注册累加器对象,通常是在rich函数的open()方法中。这里还定义了名称。
getRuntimeContext().addAccumulator("num-lines", this.numLines);
现在可以在算子函数的任何地方使用累加器,包括open()和close()方法。
this.numLines.add(1);
整个结果将存储在执行环境的execute()方法返回的JobExecutionResult对象中(目前只有在执行等待作业完成时才有效)。
myJobExecutionResult.getAccumulatorResult("num-lines");
所有累加器对每个作业共享一个名称空间。因此,您可以在您工作的不同算子函数中使用相同的累加器。Flink将在内部合并所有具有相同名称的累加器。
关于累加器和迭代的说明:目前累加器的结果只有在整个作业结束后才可用。我们还计划让上一个迭代的结果在下一个迭代中可用。您可以使用aggregator来计算每个迭代的统计信息,并根据这些统计信息来终止迭代。
自定义累加器
要实现自己的累加器,只需编写accumulator接口的实现。如果您认为您的自定义累加器应该与Flink一起,请随意创建一个拉请求。
您可以选择实现Accumulator或SimpleAccumulator。
Accumulator<V,R>是最灵活的:它为要添加的值定义了一个类型V,并为最终结果定义了一个结果类型R。例如,对于histogram,V是一个数字,R是一个histogram。SimpleAccumulator用于两种类型相同的情况,例如计数器。