2

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

我完全理解这通常不是一个好主意我也没有习惯。

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

当然,这违反了最小惊讶原则,并且可能对客户不友好-但我很好奇它是否违反了联系Iterator-只要我记录下来,我是否在规则范围内玩?

javadoc的编写似乎侧重于集合,在next()调用之间共享状态可能毫无意义,但Iterator它是一个通用接口(您可以在没有支持集合甚至没有支持任何东西的情况下实现)。

基本上,我试图在性能方面实现与享元模式相当的东西,但要保留 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第一个循环中的 s 被存储起来,因此逃脱了它们的迭代。当您稍后访问它们时,它们的状态可能是无效的(例如,它们可能看起来都像foo从初始迭代中返回的最后一个。

4

1 回答 1

0

AList可以多次包含同一个对象,并且它Iterator会在它出现在列表中的位置返回这个对象。因此,这可能不是合同禁止的事情。ASet不应包含重复项,因此不会两次返回相同的对象。

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

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

于 2013-01-17T07:32:51.280 回答