1

嗨,我正在 reducer 中执行一些计算并尝试将数据加载到 ArrayList 中。当我在稍后的代码点对 ArrayList 执行 get 操作时,ArrayList 中的所有对象都具有相同的值。

public ArrayList<some_class> temp = new ArrayList<some_class>();
//This is global variable

@Override
public void reduce(Key_class key, Iterator<some_class> values,
        OutputCollector<Text, Text> output, Reporter reporter)
                throws IOException {
    if(this.output==null){
        this.output=output;
    }

    while(values.hasNext())
    {
                    //if i print here
                    //and do the following values.next().val1
                    //I'm getting the right result
        temp.add(values.next());
    }

    System.out.println(temp.get(0).val1);//Wrong result
}

我得到如下输出:12/10/2012 10:13 12/10/2012 10:13

实际输出应为:12/10/2012 09:10 12/10/2012 10:13

感谢你的帮助。谢谢!!!

4

2 回答 2

4

价值观的实现是什么?症状的一个原因是 values.mext() 总是返回对同一对象的引用,但更改该对象的值以匹配迭代中的下一项。如果您无权访问其源代码,则可以通过在循环内为 values.next() 结果打印 System.identityHashCode() 来测试这种情况。

如果发生这种情况,您要么需要修复迭代器的实现以每次返回不同的对象,要么需要在添加到 ArrayList 之前克隆对象。

于 2013-06-02T16:22:38.107 回答
2

就像@Patricia Shanahan 已经指出的那样,对象正在被重用 - 对象的底层内容正在被更新(但所有子对象等也被重用,这取决于您的 readFields / write 方法)。

在将对象添加到 ArrayList 之前,您可以通过制作对象副本来解决这个问题:

@Override
public void reduce(Key_class key, Iterator<some_class> values,
    OutputCollector<Text, Text> output, Reporter reporter)
            throws IOException {
  if(this.output==null){
    this.output=output;
  }

  // you should out the arraylist to avoid unexpected behaviour and OOME
  temp.clear();

  while(values.hasNext())
  {
    // you'll need a copy of the configuration - conf
    temp.add(
        ReflectionUtils.copy(conf, values.next(), new some_class()));
  }
}
于 2013-06-02T22:02:34.680 回答