在reducer中迭代自定义可写组件的java问题

bmvo0sr5  于 2021-05-29  发布在  Hadoop
关注(0)|答案(1)|浏览(444)

我在mr作业的map阶段使用一个定制的可写类作为valueout,该类有两个字段,一个 org.apache.hadoop.io.Text 以及 org.apache.hadoop.io.MapWritable . 在reduce函数中,我遍历每个键的值并执行两个操作,1。过滤器,2。聚合。在过滤器中,我有一些规则来检查mapwritable中的某些值(键为 Text 和价值 IntWritable 或者 DoubleWritable )满足某些条件,然后我只需将它们添加到arraylist中。在筛选操作的最后,我有一个自定义可写对象的筛选列表。在聚合阶段,当我访问对象时,最后一个成功过滤的对象覆盖了arraylist中的所有其他对象。在经历了列表的一些类似问题之后,最后一个对象覆盖了所有其他对象,我确认我没有静态字段,也没有通过设置不同的值来重用相同的自定义可写字段(这被引用为此类问题的可能原因)。对于减速器中的每个键,我都确保 CustomWritable , Text 钥匙和钥匙 MapWritable 是新对象。
此外,我还执行了一个简单的测试,在reduce中消除了filter和aggregate操作,只需遍历这些值,并使用for循环将它们添加到arraylist中。在循环中,每次向列表中添加customwritable时,我都会记录列表中所有内容的值。在将元素添加到列表之前和之后,我都进行了日志记录。两个日志都显示前一组元素已被覆盖。我不知道这怎么会发生。一旦循环访问了值的iterable中的下一个元素 for ( CustomWritable result : values ) ,列表内容已修改。我想不出这种行为的原因。如果有人能解释一下这一点,那将是非常有帮助的。谢谢。

9jyewag0

9jyewag01#

reducer中的“values”迭代器在迭代时重用该值。这是一种提高性能和减少内存占用的技术。在幕后,hadoop将下一条记录反序列化到同一个java对象中。如果你需要“记住”一个对象,你需要克隆它。
您可以利用可写接口并使用原始字节填充新对象。

IntWritable first = WritableUtils.clone(values.next(), context.getConfiguration());
IntWritable second = WritableUtils.clone(values.next(), context.getConfiguration());

相关问题