Java Spark3避免lambda强制转换:引用不明确

6mw9ycah  于 6个月前  发布在  Apache
关注(0)|答案(1)|浏览(87)

我一直在Spark 2上开发很多东西,我正试图将我的代码库转移到Spark 3上。
问题是,我所有的lambda代码与数据集不再工作,引用Map是含糊不清的:

java: reference to map is ambiguous
  both method <U>map(scala.Function1<T,U>,org.apache.spark.sql.Encoder<U>) in org.apache.spark.sql.Dataset and method <U>map(org.apache.spark.api.java.function.MapFunction<T,U>,org.apache.spark.sql.Encoder<U>) in org.apache.spark.sql.Dataset match

字符串
下面是一个在Spark3上复制它的快速代码:

public static void main(String[] args) {
        SparkSession
                .builder()
                .master("local[1]")
                .getOrCreate()
                .createDataset(Arrays.asList("A", "b", "C"), Encoders.STRING())
                // error is here
                .map(v -> v.toLowerCase(), Encoders.STRING())
                .show();
    }


这个错误也适用于其他所有的数据集转换,如filter,flatMap,.
我尝试了不同版本的Java(8,11和17),但错误总是相同的。
在过去,我曾经用Intellij使用Scala插件遇到过类似的问题,但现在,即使是Java也无法用Spark3编译此代码。
它甚至不能与方法引用一起工作。唯一的修复是转换:

public static void main(String[] args) {
        SparkSession
                .builder()
                .master("local[1]")
                .getOrCreate()
                .createDataset(Arrays.asList("A", "b", "C"), Encoders.STRING())
                // A cast fixes the issue
                .map((MapFunction<String, String>) v -> v.toLowerCase(), Encoders.STRING())
                .show();
    }


或者创建一个实现所需函数的类

public class Main {

    public static void main(String[] args) {
        SparkSession
                .builder()
                .master("local[1]")
                .getOrCreate()
                .createDataset(Arrays.asList("A", "b", "C"), Encoders.STRING())
                .map(new LowerCaseSparkFunction(), Encoders.STRING())
                .show();
    }

}

class LowerCaseSparkFunction implements MapFunction<String, String> {

    @Override
    public String call(String s) throws Exception {
        return s.toLowerCase();
    }
}


我发现铸造解决方案太冗长,我需要更新很多代码才能让它工作。还有其他解决方案吗?

lg40wkob

lg40wkob1#

一个小的助手函数家族(或使用Scala),例如:

public static <T, R> MapFunction<T, R> mapF(MapFunction<T,R> function)
{
    return function;
}

.map(mapF(v -> v.toLowerCase()), Encoders.STRING())

字符串
是第三种选择,类型推断将得到改进,而你最困难的任务是记住函数名和导入。
为源代码中的每个歧义添加一个静态函数到util类。

相关问题