IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Flink DataStream Java Lambda 表达式的限制 -> 正文阅读

[大数据]Flink DataStream Java Lambda 表达式的限制

?
在这里插入图片描述

原文:Flink DataStream Java Lambda 表达式的限制

Java 8 引入了一些新的语言特性,旨在实现更快、更清晰的编码。凭借最重要的特性 ‘Lambda 表达式’,打开了函数式编程的大门。Lambda 表达式允许以直接的方式实现和传递函数,而无需声明额外的(匿名)类。Flink 支持对 Java API 的所有算子使用 Lambda 表达式,但是当 Lambda 表达式使用 Java 泛型时,我们都必须显式声明类型信息。

下面通过两个例子来展示如何使用 Lambda 表达式并描述使用上的限制。

1. MapFunction与泛型

以下示例说明了如何实现一个简单的 map() 函数,该函数使用 Lambda 表达式对其输入进行平方,输出值为本身和平方的元组:

env.fromElements(1, 2, 3)
  .map(i -> Tuple2.of(i, i*i))
  .print();

由于在 map 函数中使用了 Lambda 表达式,结果抛出如下异常信息:

在这里插入图片描述

从上面报错信息可以知道 Lambda 中由于使用了泛型导致类型擦除而抛异常。map() 函数返回值 Tuple2<Integer, Integer> 被擦除为 Tuple2 map(Integer value)。在许多情况下,当涉及 Java 泛型时,Lambda 方法无法为自动类型提取提供足够的信息。报错信息中也给出了解决方案:

  • 使用一个(匿名)类来代替实现 ‘org.apache.flink.api.common.functions.MapFunction’ 接口。
  • 必须使用类型信息显式指定类型。

下面我们详细看一下具体的对应方案。

1.1 匿名内部类方式

使用匿名内部类来代替实现 ‘org.apache.flink.api.common.functions.MapFunction’ 接口:

env.fromElements(1, 2, 3)
    .map(new MapFunction<Integer, Tuple2<Integer, Integer>>() {
        @Override
        public Tuple2<Integer, Integer> map(Integer i) throws Exception {
            return new Tuple2<Integer, Integer>(i, i * i);
        }
    })
    .print();

为什么采用匿名内部类就没有问题?因为匿名内部类会编译成相关的类字节码存储在 class 文件中,而 Lambda 表达式只是 Java 的语法糖并不会存在相关的类字节码,Lambda 表达式是在运行时调用 invokedynamic 指令,亦即在第一次执行其逻辑时才会确定。因此 Lambda 表达式比起匿名内部类,会丢失更多的类型信息。

1.2 自定义类方式

使用自定义类来代替实现 ‘org.apache.flink.api.common.functions.MapFunction’ 接口:

public static class MyMapFunction implements MapFunction<Integer, Tuple2<Integer, Integer>> {
    @Override
    public Tuple2<Integer, Integer> map(Integer i) {
        return Tuple2.of(i, i*i);
    }
}

env.fromElements(1, 2, 3)
  .map(new MyMapFunction())
  .print();

1.3 returns方式

使用 returns 语句显示的指明类型信息:

env.fromElements(1, 2, 3)
    .map(i -> Tuple2.of(i, i*i))
    .returns(Types.TUPLE(Types.INT, Types.INT))
    .print();

2. FlatMap与泛型

在下面示例中我们在 flatMap() 函数中使用 Lambda 表达式将字符串拆成多行:

env.fromElements("1,2,3", "4,5")
    .flatMap((String input, Collector<String> out) -> {
        String[] params = input.split(",");
        for(String value : params) {
            out.collect(value);
        }
    })
    .print();

由于 flatMap() 函数签名 void flatMap(IN value, Collector out) 中有泛型 Collector,所以在编译是进行泛型类型擦除,最终编译为 flatMap(IN value, Collector out)。这使得 Flink 无法自动推断输出类型的类型信息。所以在 flatMap() 函数中使用 Lambda 表达式会抛出类似如下的异常:

在这里插入图片描述

跟 MapFunction 的报错信息基本一致,都是由于 Lambda 中使用泛型导致类型擦除。解决方案也类似:

  • 使用一个(匿名)类来代替实现 ‘org.apache.flink.api.common.functions.FlatMapFunction’ 接口。
  • 必须使用类型信息显式指定类型。

下面我们详细看一下具体的对应方案。

2.1 匿名内部类方式

使用匿名内部类来代替实现 ‘org.apache.flink.api.common.functions.FlatMapFunction’ 接口:

env.fromElements("1,2,3", "4,5")
    .flatMap(new FlatMapFunction<String, String>() {
        @Override
        public void flatMap(String input, Collector<String> out) throws Exception {
            String[] params = input.split(",");
            for(String value : params) {
                out.collect(value);
            }
        }
    })
    .print();

2.2 自定义类方式

使用自定义类来代替实现 ‘org.apache.flink.api.common.functions.FlatMapFunction’ 接口:

public static class MyFlatMapFunction implements FlatMapFunction<String, String> {
    @Override
    public void flatMap(String input, Collector<String> out) throws Exception {
        String[] params = input.split(",");
        for(String value : params) {
            out.collect(value);
        }
    }
}

env.fromElements("1,2,3", "4,5")
  .flatMap(new MyFlatMapFunction())
  .print();

2.3 returns方式

使用 returns 语句显示的指明类型信息:

env.fromElements("1,2,3", "4,5")
  .flatMap((String input, Collector<String> out) -> {
      String[] params = input.split(",");
      for(String value : params) {
          out.collect(value);
      }
  })
  .returns(String.class)
  .print();

欢迎关注我的公众号和博客:

在这里插入图片描述

参考:

?

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-10-09 16:21:04  更:2021-10-09 16:22:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:28:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码