从Iterator返回相同的对象<! - ? - >

时间:2013-01-17 07:21:32

标签: java performance optimization iterator

是否有效 - 即在联系内,Iterator返回与先前迭代相同(可变)的对象,或具有共享可变状态的新对象作为先前对象?也就是说,可以调用next()来使先前调用返回的对象无效,只要它被记录下来了吗?

我完全理解这不是一个好主意一般,而且我没有养成习惯。

但是,在某些情况下,重用相同的底层对象或具有共享内部的新对象(因此可能使先前返回的对象的内部无效)具有重要性和可测量性。一个很好的例子是当迭代器返回的对象以一些偏移和长度指向包含Iterable的缓冲区数组时,并且在检索后续对象时可能会覆盖此数组。

当然这违反了最不惊讶的原则,并且可能是客户不友好 - 但我很好奇它是否违反Iterator的联系 - 只要我记录它,我是否遵守规则?< / p>

javadoc似乎是专注于集合,其中next()调用之间的共享状态可能毫无意义,但Iterator是一个通用接口(您可以在没有支持集合,甚至没有支持任何)。

基本上我正在尝试在flyweight模式中实现可比性,性能方面的东西,但要保留Java迭代器的细节。

遵循此模式的迭代器可以通过以下方式安全使用:

for (Foo foo : FooIterable) {
  if (foo.method()) {
    System.println("ha!");
  }
}

因为foo的每个实例都不会从一次迭代转移到另一次迭代。但是,类似下面的内容通常不起作用:

List<Foo> allTheFoos = ...;
for (Foo foo : FooIterable) {
  allTheFoos.add(foo);
}

for (Foo foo : allTheFoos) {
  ...
}

由于第一个循环中的foo被存储起来,因此逃避了它们的迭代。当您稍后访问它们时,它们的状态可能无效(例如,它们可能看起来都像是从初始迭代返回的最后一个foo

1 个答案:

答案 0 :(得分:0)

List可以多次包含同一个对象,并且Iterator会将此对象返回到列表中出现的位置。因此,这可能不是合同所禁止的。 Set不应包含重复项,因此不会两次返回相同的对象。

集合永远不会修改或使其成员无效,但是在迭代器本身内部存在类似于您的情况:如果集合已被修改,它将变为无效(并在调用时抛出异常)。这可能是提示要在返回的对象变为无效时执行的解决方案。

也许你的迭代可以更好地返回有关该更改对象的包装器,以确保对先前返回的,现在无效的包装器抛出异常的所有调用。