杂记-flink中使用lambda

838 阅读2分钟

最近在学习flink的过程中会涉及到使用某算子来进行et。由于某些算子需要自己实现,每次实现的形式又相对冗余,代码量较多,看上去也不够时尚,最主要idea还老是出现下划线置灰,像这种

以我一贯的编码风格,是绝对无法忍受下划线的。所以就打算根据idea的提示使用lambda进行改写。

lambda

lambda,是 java 1.8 推出的新特性

Lambda 表达式是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象,是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包。

看起来有点抽象,如果之前有过Python编程经验的话,应该对lambda表达式一点也不陌生。实际上它就是一个匿名函数。以上的编码经过改写以后变成如下

这样一改,瞬间感觉清新脱俗了不少,简洁优雅了不少,看起来一点也不笨重。那么为啥它可以这么改呢?

首先,通过org.apache.flink.streaming.api.datastream.DataStream源码,可以看到flatMap的重载方法均要接收一个FlatMapFunction对象

public <R> SingleOutputStreamOperator<R> flatMap(FlatMapFunction<T, R> flatMapper) {
        TypeInformation<R> outType = TypeExtractor.getFlatMapReturnTypes((FlatMapFunction)this.clean(flatMapper), this.getType(), Utils.getCallLocationName(), true);
        return this.flatMap(flatMapper, outType);
    }
    
public <R> SingleOutputStreamOperator<R> flatMap(FlatMapFunction<T, R> flatMapper, TypeInformation<R> outputType) {
        return this.transform("Flat Map", outputType, (OneInputStreamOperator)(new StreamFlatMap((FlatMapFunction)this.clean(flatMapper))));
    }

跳转该接口定义

@FunctionalInterface
@Public
public interface FlatMapFunction<T, O> extends Function, Serializable {
    void flatMap(T var1, Collector<O> var2) throws Exception;
}

在接口上,我们看到在接口定时上使用@FunctionalInterface注解。该注解是1.8后才新增的。主要用来进行函数式编程,也是lambda实现的基础。函数式接口中只能声明一个可被实现的方法,你不能声明了一个 run方法,又声明一个 start方法,到时候编译器就不知道用哪个接收了。

lambda注意事项

Lambda表达式只能针对函数式接口使用(函数式接口:接口里只有一个抽象方法),使用注解(@FunctionalInterface)可以强制接口是函数式接口。 Lambda 表达式由三个部分组成:第一部分为一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数;第二部分为一个箭头符号:->;第三部为方法体,可以是表达式和代码块。

(parameters) -> expression ##一条语句的时候
(parameters) -> { statements; } ##多条语句的时候,需要return返回值的时候
() -> { statements; } ##没有参数