gpt4 book ai didi

java - 接口(interface)作为Mapper值输出

转载 作者:可可西里 更新时间:2023-11-01 14:35:48 25 4
gpt4 key购买 nike

我有一个映射器,其输出值设置为如下接口(interface):

public interface OutValue extends Writable {}

在映射期间,我创建具有此签名的对象并发出它们:

public class OutRecord implements OutValue {}

我的Mapper是这样的:

public class ExampleMapper extends
Mapper<LongWritable, Text, ExampleKey, OutValue > {}

但是我收到了这个错误:

java.io.IOException: Type mismatch in value from map: expected OutValue, recieved OutRecord
at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.collect(MapTask.java:850)
at org.apache.hadoop.mapred.MapTask$NewOutputCollector.write(MapTask.java:541)
at org.apache.hadoop.mapreduce.TaskInputOutputContext.write(TaskInputOutputContext.java:80)

所以我的第一直觉是尝试像这样转换它:

context.write(key, (OutValue) record);

但是我仍然得到同样的错误。这在我将映射器输出类型从 OutRecord 类更改为 OutValue 接口(interface)之前起作用。我这样做的原因是我有许多类型的 OutRecord 类我想从这个映射器发出。

这可能吗? OutValue 是否必须是类而不是接口(interface)?

更新:

我挖掘了 Hadoop 0.20.205.0 的一些源代码,发现了这个:

public synchronized void collect(K key, V value, int partition) throws IOException {
...
if (value.getClass() != valClass) {
throw new IOException("Type mismatch in value from map: expected "
+ valClass.getName() + ", recieved "
+ value.getClass().getName());
}

所以他们使用的运行时检查要求类中严格相等,他们不检查子类/接口(interface)等。当然这是一个常见的用例,有人试过这样做吗?

最佳答案

对类型进行这种严格检查有几个原因:

如果您要输出到序列文件,则此文件的标题包含键和值类的类型。 Hadoop 然后在读回序列文件时使用已注册的序列化程序创建这些对象的新实例。

如果你注册为输出类型的类是接口(interface),或者你输出的实际对象是声明类型的子类,那么你将无法在运行时实例化接口(interface),或者实例化的类不会是您期望的子类(并且您的反序列化很可能会因 IOException 而失败)。

(当我开始输入这个时,我想到了另一个原因,但我暂时忘记了)。

现在,如果您希望能够输出不同的类型(子类),那么考虑使用 GenericWritable “包装”你的对象 - 在这种情况下,每个对象输出前面都有一个类型 - 查看 source和 javadocs 了解更多细节。

请注意,这是有一定代价的——输入和输出不会利用在 hadoop 其他地方看到的对象重用,但您可能没有注意到这个代价。您可以重写 GenericWritable 以提高效率,方法是为看到的每个实例类型合并一个对象并以通常的方式重新使用它。

关于java - 接口(interface)作为Mapper值输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11126362/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com