java.lang.ClassCastException:scala.Tuple2无法转换为java.lang.Iterable

java.lang.ClassCastException:scala.Tuple2无法转换为java.lang.Iterable,java,apache-spark,Java,Apache Spark,在Spark中使用Java,我想解析一个名为artist_data.txt的文本文档; 我首先创建了JavaRDD JavaRDD rawArtistData=sc.textFile(“src/main/resources/artist_data.txt”); 现在来解析这个文档,它有Tab sperator,但也有错误的行,其中的行数似乎已损坏。它们不包含选项卡, 或者它们无意中包含了换行符。所以我需要使用平面图的方法 现在通过运行下面的代码,我得到了一个错误; java.lang.Class

在Spark中使用Java,我想解析一个名为artist_data.txt的文本文档; 我首先创建了JavaRDD

JavaRDD rawArtistData=sc.textFile(“src/main/resources/artist_data.txt”); 现在来解析这个文档,它有Tab sperator,但也有错误的行,其中的行数似乎已损坏。它们不包含选项卡, 或者它们无意中包含了换行符。所以我需要使用平面图的方法

现在通过运行下面的代码,我得到了一个错误; java.lang.ClassCastException:scala.Tuple2无法转换为java.lang.Iterable

JavaRDD artistByID0=rawArtistData
.flatMap(新的flatMap函数(){
私有静态最终长serialVersionUID=1L;
@抑制警告(“未选中”)
公共Iterable调用(字符串s){
字符串[]sarray=s.split(“\t”);
返回(Iterable)新元组2
(Integer.parseInt(sarray[0]),sarray[1].trim();
}
});
javapairdd artistByID=javapairdd.fromJavaRDD(artistByID0);

System.out.println(artistByID.count())简短的回答是,您已经告诉FlatMapFunction您正在返回一个Tuple2的iterable。显然FlatMapFunction希望返回您在类中定义的iterable。所以最简单的答案是制作一个LinkedList>,只添加元组并返回它

下面是一个可能的更改,用于统计API

public Iterable<Tuple2<Integer, String>> call(String s) {
    String[] sarray = s.split("\t");
    LinkedList<Tuple2<Integer, String>> r = new LinkedList<>();
    Tuple2<Integer, String> t = new Tuple2<Integer, String> (Integer.parseInt(sarray[0]), sarray[1].trim());
    r.add(t)
    return r;
}
public Iterable调用(字符串s){
字符串[]sarray=s.split(“\t”);
LinkedList r=新建LinkedList();
tuple2t=newtuple2(Integer.parseInt(sarray[0]),sarray[1].trim());
r、 加(t)
返回r;
}

很长的答案其实是一个问题:为什么不使用Scala?最基本的是Java。您可以从那里开始工作。

这是因为
flatMap
需要一个列表,它会将内部列表截断为一个列表。当您一次拆分和解析时,实际上只需要
map
函数,它将直接返回
元组

flatMap
的一个更典型的用例是直接从拆分返回数组,这将导致所有数组被截断为一个列表,这样您就拥有了所有的单词,而不是一堆单独的单词列表

根据您的评论,所显示的代码示例似乎没有显示您真正的用例。如果由于数据不正确而可能不返回任何内容,则需要以下内容:

JavaRDD<Tuple2<Integer, String>> artistByID0 = rawArtistData
                .flatMap(new FlatMapFunction<String, Tuple2<Integer, String>>() {
                    private static final long serialVersionUID = 1L;
                    @SuppressWarnings("unchecked")
                    public Iterable<Tuple2<Integer, String>> call(String s) {
                         String[] sarray = s.split("\t");
                         List<Tuple2<Integer, String>> returnList = new ArrayList<Tuple2<Integer, String>>();
                         if(sarray.length >= 2) 
                           returnList.add(new Tuple2<Integer, String> (Integer.parseInt(sarray[0]), sarray[1].trim()));
                         return returnList;
                        );
                    }
                });
JavaRDD artistByID0=rawArtistData
.flatMap(新的flatMap函数(){
私有静态最终长serialVersionUID=1L;
@抑制警告(“未选中”)
公共Iterable调用(字符串s){
字符串[]sarray=s.split(“\t”);
List returnList=new ArrayList();
如果(sarray.length>=2)
添加(新的Tuple2(Integer.parseInt(sarray[0]),sarray[1].trim());
退货清单;
);
}
});

请注意,如果拆分成功拆分为2个或多个项目,则现在仅返回包含项目的列表

谢谢,但是当调用FlatMapFunction时,它确实期望Iterable;这里是我找到的FlatMapFunction的定义,包org.apache.spark.api.java.function;导入java.io.Serializable;/***从每个输入记录返回零个或多个输出记录的函数。*/公共接口FlatMapFunction扩展可序列化{public Iterable调用(T)引发异常;}Tuple2不可序列化。在上面的代码中,您正在强制Tuple2转换为Iterable。老实说,我很惊讶编译器竟然允许这样做。您需要创建某种类型的Iterable。一个简单的低内存版本是LinkedList。此代码示例对于FlatMap没有意义,因为它希望始终返回1个元素。嗨,Justin,“map”的问题,它不工作,因为文件已损坏;该文件包含由选项卡分隔的艺术家ID和名称。然而,将文件直接解析为(Int,String)元组将失败,因为少数行似乎已损坏。它们不包含制表符,或者无意中包含换行符。这些行会导致NumberFormatException,理想情况下,它们根本不会映射到任何东西。因此,我应该应用flatMap函数(它允许返回0、1或多个结果)来构建一个包含对(ID、名称)的JavaPairRDD。谢谢你,Justin,你能在这里提供帮助吗,我是java和Spark世界的新手,正在学习……Justin,我认为你对这个问题有点过火。他得到了类型错误,因为他没有遵循API。什么时候使用什么是好东西,但我不认为它对这个问题有帮助。嗨,贾斯汀,我无法实例化类型列表,谢谢lot@ravi666其中很多都是通过查看javadocs得到的,但是我已经适当地更新了我的答案。