欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > 55、Flink 中使用 Java Lambda 表达式详解

55、Flink 中使用 Java Lambda 表达式详解

2024/11/6 3:02:16 来源:https://blog.csdn.net/m0_50186249/article/details/140144288  浏览:    关键词:55、Flink 中使用 Java Lambda 表达式详解
1)概述
1.注意

Flink 支持对 Java API 的所有算子使用 Lambda 表达式,但是,当 Lambda 表达式使用 Java 泛型时,需要 显式 地声明类型信息。

2.示例和限制

示例: map() 函数使用 Lambda 表达式计算输入值的平方。

不需要声明 map() 函数的输入 i 和输出参数的数据类型,因为 Java 编译器会对它们做出推断。

env.fromElements(1, 2, 3)
// 返回 i 的平方
.map(i -> i*i)
.print();

由于 OUTInteger 而不是泛型,所以 Flink 可以从方法签名 OUT map(IN value) 的实现中自动提取出结果的类型信息。

但像 flatMap() 这样的函数,它的签名 void flatMap(IN value, Collector out) 被 Java 编译器编译为 void flatMap(IN value, Collector out)。Flink 就无法自动推断输出的类型信息了。

Flink 很可能抛出如下异常:

org.apache.flink.api.common.functions.InvalidTypesException: The generic type parameters of 'Collector' are missing.In many cases lambda methods don't provide enough information for automatic type extraction when Java generics are involved.An easy workaround is to use an (anonymous) class instead that implements the 'org.apache.flink.api.common.functions.FlatMapFunction' interface.Otherwise the type has to be specified explicitly using type information.

此时需要 显式 指定类型信息,否则输出将被视为 Object 类型,这会导致低效的序列化。

DataStream<Integer> input = env.fromElements(1, 2, 3);// 必须声明 collector 类型
input.flatMap((Integer number, Collector<String> out) -> {StringBuilder builder = new StringBuilder();for(int i = 0; i < number; i++) {builder.append("a");out.collect(builder.toString());}
})
// 显式提供类型信息
.returns(Types.STRING)
// 打印 "a", "a", "aa", "a", "aa", "aaa"
.print();

当使用 map() 函数返回泛型类型的时候也会发生类似的问题。下面示例中的方法签名 Tuple2<Integer,Integer> map(Integer value) 被擦除为 Tuple2 map(Integer value)

import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.java.tuple.Tuple2;env.fromElements(1, 2, 3).map(i -> Tuple2.of(i, i))    // 没有关于 Tuple2 字段的信息.print();

解决方式如下

import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.tuple.Tuple2;// 使用显式的 ".returns(...)"
env.fromElements(1, 2, 3).map(i -> Tuple2.of(i, i)).returns(Types.TUPLE(Types.INT, Types.INT)).print();// 使用类来替代
env.fromElements(1, 2, 3).map(new MyTuple2Mapper()).print();public static class MyTuple2Mapper extends MapFunction<Integer, Tuple2<Integer, Integer>> {@Overridepublic Tuple2<Integer, Integer> map(Integer i) {return Tuple2.of(i, i);}
}// 使用匿名类来替代
env.fromElements(1, 2, 3).map(new MapFunction<Integer, Tuple2<Integer, Integer>> {@Overridepublic Tuple2<Integer, Integer> map(Integer i) {return Tuple2.of(i, i);}}).print();// 也可以像这个示例中使用 Tuple 的子类来替代
env.fromElements(1, 2, 3).map(i -> new DoubleTuple(i, i)).print();public static class DoubleTuple extends Tuple2<Integer, Integer> {public DoubleTuple(int f0, int f1) {this.f0 = f0;this.f1 = f1;}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com