【问题标题】:Java: Copy collection with the use of IteratorJava:使用迭代器复制集合
【发布时间】:2011-11-29 18:00:03
【问题描述】:

我有一个方法,它作为参数有一个集合的迭代器。在我要复制集合的方法中,迭代器“指向”。 然而,只有最后一个集合条目出现在集合副本中,它存在 N 次,其中 N 是原始集合的大小。

public void someMethod(Iterator<Node> values) {
  Vector<Node> centralNodeNeighbourhood = new Vector<Node>();
  while (values.hasNext()) {
    Node tmp = values.next();
    centralNodeNeighbourhood.add(tmp);
  }
  ...
  //store the centralNodeNeighbourhood on disk
}

示例“原始集合”:

1
2
3

示例“centralNodeNeighbourhood 集合”:

3
3
3

有人可以指出我的错误吗?我无法更改方法 args,我只能将 Iterator 获取到集合中,对此无能为力。

更新(回答一些问题)

while (values.hasNext()) {
            Node tmp = values.next();
            System.out.print("Adding = "+tmp.toString());
            centralNodeNeighbourhood.add(tmp);
        }

打印正确的原始集合元素。 我不知道原始集合是什么类型,但 Iterator 来自 std java。方法是

public class GatherNodeNeighboursInfoReducer extends MapReduceBase
        implements Reducer<IntWritable, Node, NullWritable, NodeNeighbourhood>{
    public void reduce(IntWritable key, Iterator<Node> values,
                   OutputCollector<NullWritable, NodeNeighbourhood> output, Reporter reporter) throws IOException {...}
}

来自 OLD Hadoop api 的方法(Hadoop 版本 0.20.203.0)

已解决 我在每次迭代时都制作了 tmp 对象的副本,并将这个副本添加到 centralNodeNeighbourhood 集合中。这解决了我的问题。感谢您的所有(快速)帮助。

【问题讨论】:

  • 如果你在这个循环中转储tmp,它会显示你的期望吗?
  • 给定迭代器的操作方式取决于提供它的类的实现;因此,为您提供迭代器的类很可能在其设计中存在错误。你给它的这个集合是标准 java 库的一部分,还是用户制作的?
  • 测试是否使用 == 运算符获得相同的实例。告诉我们测试结果。
  • @Puce 是的,与 centralNodeNeighbourhood.get(0) 相比,每个 tmp 实例的“==”运算符都是正确的,但 tmp 对象内的数据每次迭代都不同。

标签: java collections iterator copying


【解决方案1】:

Iterator 似乎每次都返回相同的 Node 对象。如果是这样,您需要在将其添加到集合之前获取节点的副本。 (否则,您每次都将添加相同的对象,并且它将具有上次设置的值)

【讨论】:

  • 嗯?我真的不明白你建议修复什么,但如果 Iterator 坏了,你就完蛋了,不是吗?
  • 有些迭代器每次都返回相同的对象。即每次调用 values.next() 时,您实际上都得到了相同的对象(设置为不同的值)通常被认为是混淆但合法。
  • 这里是一个集合的例子,它的 entrySet() 迭代器每次在 Next() 中返回相同的对象。 tech.puredanger.com/2009/06/11/collections-puzzler
  • @PeterLawrey 幸运的是,我认为这样做的 JDK 集合已在 JDK7 中修复。
  • 如果每次迭代都打印出System.identityHashCode(tmp); 会发生什么?每次都是一样的值吗?为了验证彼得的说法,只需确保为每个对象获得不同的值。
【解决方案2】:

Hadoop 的reduce 方法指定它重用其迭代器中的值对象。这是一件可怕的事情,但它就是这样做的。

框架将重用传递给 reduce 的键和值对象,因此应用程序应该克隆他们想要保留副本的对象。在许多情况下,所有值都组合成零或一个值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    • 2017-12-08
    • 2016-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-05
    相关资源
    最近更新 更多