Java 将RDD的值映射到它们的字典值

Java 将RDD的值映射到它们的字典值,java,dictionary,apache-spark,Java,Dictionary,Apache Spark,我有一段代码: List tmp = colRDD.collect(); int ctr = 0; for(Object o : tmp){ if (!dictionary.containsKey(o)) { dictionary.put(o, ctr++); } } revDictionary = dictionary.entrySet().stream() .collect(Collectors.toMap(Entry::getValue, c

我有一段代码:

List tmp = colRDD.collect();
int ctr = 0;
for(Object o : tmp){
    if (!dictionary.containsKey(o)) {
        dictionary.put(o, ctr++);
    }
}
revDictionary = dictionary.entrySet().stream()
        .collect(Collectors.toMap(Entry::getValue, c -> c.getKey()));
colRDD = colRDD.map(x ->  {return dictionary.get(x);});
colRDD = colRDD.map(x ->  {return dictionary.get(x);});
首先,我具体化RDD并将每个值放入一个哈希表中,其中RDD值是键。 然后,我想将RDD中的每个值映射到它们的字典值。
但是,我得到一个
任务不可序列化
错误。为什么会这样?

这是由于试图从执行器评估的代码中访问驱动程序的变量作用域造成的

根据您的示例代码,最可能的罪魁祸首是这一行代码中的
dictionary

List tmp = colRDD.collect();
int ctr = 0;
for(Object o : tmp){
    if (!dictionary.containsKey(o)) {
        dictionary.put(o, ctr++);
    }
}
revDictionary = dictionary.entrySet().stream()
        .collect(Collectors.toMap(Entry::getValue, c -> c.getKey()));
colRDD = colRDD.map(x ->  {return dictionary.get(x);});
colRDD = colRDD.map(x ->  {return dictionary.get(x);});
然而,问题也可能来自代码中比您在这里提供的更高的层次,因此您可能也需要检查这一点


这是因为
字典
驻留在驱动程序的内存中,驱动程序可能运行在一个单独的JVM实例中,而不是在执行器中。传递给
colRDD.map
的lambda由执行器而不是驱动程序计算。函数被序列化为要执行的任务,发送给要运行的执行器。但是Spark引擎无法序列化任务,因为
字典周围的“关闭”导致异常。

我知道错误来自于此。但请不要理解原因。添加了更多详细信息以帮助理解发生了什么。@ImDarrenG的答案是正确的,但是最好使用广播,不要在每次调用map时都发送字典。幸运的是,这不起作用,因为示例中正在修改字典。OP问了另一个关于如何解决问题的问题,我在评论中提出了一种方法,但我不知道,所以如果你还没有:)OP一定删除了另一个问题对不起