迭代器的下一个方法

5
ResultSet 接口中,有一个返回布尔值的 next 方法,然后您可以直接使用 get 方法访问当前记录。
为什么来自 java.utilIterator 不删除 hasNext() 方法,而只是有一个 next 方法将光标移动到下一个元素并返回 boolean

我尝试过类似这样的代码 while(( o= itr.next() ) != null),但是我得到了NoSuchElementException异常。如果你查看各种类中迭代器next()方法的实现,你会发现NoSuchElementException是通过检查不同的条件抛出的。例如,Abstractlist有一个美丽的catch块来抛出IndexOutOfBoundsException以抛出NoSuchElementException,在LinkedBlockingDeque类中我们有next != null的检查。 - Delta
3个回答

8

由于next()当前返回下一个项。

Java也可以像.NET一样以相同的方式实现迭代器模式,其中MoveNext()返回布尔值,然后Current属性带有“当前”值-但仍然是两个成员...

另一种选择是有一个返回值,封装了“是否有值”和“如果有值是什么”的两个概念-一种类型的Maybe类型。当然在Java中,这意味着在每次迭代时分配一个新对象,这并不理想...


2

因为你仍然需要另一个函数来检索值,所以没有任何收益。

在ResultSet中, next()能帮助你跳转到下一条记录, 如果没有下一条记录就返回false。然后你可以用getString()、getInt()或者其他方式来检索字段值。所以你要写出以下代码:

while (rs.next())
{
  name=rs.getString("name"); // or whatever
  ... do something with name ...
}

在迭代器中,hasNext()方法返回true或false,以指示是否有另一条记录。然后您调用next()方法来检索值。因此您写的代码如下:

while (iter.hasnext())
{
  name=iter.next(); // or whatever
  ... do something with name ...
}

模式最终变得非常相似。不幸的是,实现不一致。也就是说,ResultSet.next 不仅告诉您是否已经到达末尾,而且还会推进位置,而 Iterator.hasNext 告诉您是否已经到达末尾,但不会推进位置。但实际使用方式非常相似。

将 Iterator.hasNext 和 Iterator.next 结合成一个函数并不会真正起作用。你怎么知道你到达了结尾?你可以说它在结尾处返回 null ... 但如果 null 是列表中的有效值呢?我想你可以添加一些魔法值,但你仍然有区分魔法含义和列表中恰好具有该值的条目的问题。例如,如果您有一个整数列表,您可以说 -1 表示列表结束,但是如果列表包括值为 -1 的值呢?

我看到的唯一其他选择是让 next() 函数返回一个对象,该对象包括列表结束指示以及(如果适用)该值。但这将很难使用。你必须写类似于:

while (true)
{
  IterableResult ir=iter.next();
  if (ir.end)
  {
    break;
  }
  else
  {
    name=ir.value;
    ... do something with name ... 
  }
}

看起来这并没有带来任何好处。

也许有其他更好的方法,但我想不到。而且显然,迭代器接口的创建者们也想不出更好的办法!:-)


有所不同。ResultSet 不会像首先获取记录并在记录对象上执行 getXXX,然后将光标移动到下一个对象,而是在单个语句中将光标移动到下一个对象,并通过 getXXX() 方法访问该对象的成员。您实际上不会通过 getXXX 方法获取整个记录对象。 - Delta
@Delta 绝对正确。但使用方式仍然相似。 - Jay

0

ResultSetnext() 方法类似于迭代器的 hasNext() 方法。而 ResultSet 的大多数其他方法则是替代了迭代器的单个 next() 方法。

我想问另一个问题:为什么他们没有让 ResultSet 实现带泛型的迭代器或至少实现可迭代接口?我认为答案是因为在 Iterator 之前,ResultSet 就已经出现在 Java 中了。不久之后,出现了许多类似 ORM 的工具,所以大多数人都不直接使用 JDBC,也不处理 ResultSet

但我不是 JDK 的历史学家,这只是我的猜测。


另外,Iterable.next返回单个值,而在执行ResultSet.next之后,您可以执行多个getXXX来检索许多值。我想ResultSet可以被实现为返回“Record”对象的迭代器,然后您可以从Record中提取字段。我想那可能会更一致。 - Jay
1
确实,ResultSet在Iterator之前就存在于Java中,但是自Java 1.0版本以来,Java就已经有了Enumeration,它是Iterator的前身,如果他们想这样做,就可以使用它。 - Jay
@Jay,你对Record的建议正是我想要的。 - AlexR
ResultSet 的迭代可能会产生一个“预期”的异常,而使用 Iterator 则不会发生这种情况。 - Tom Hawtin - tackline
嗯,他们本来可以这样做的。这会创建一个更多的类来处理,但可以说增加了一致性。我不确定有没有任何重大优势。 (耸肩) - Jay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接