“无限”迭代器是糟糕的设计吗?[已关闭]

2022-08-31 14:56:17

提供“无限”的实现通常被认为是不好的做法吗?即,对 always(*) 的调用在何处返回 true?IteratorhasNext()

通常我会说“是”,因为调用代码的行为可能不稳定,但在下面的实现中将返回true,除非调用方从列表中删除迭代器初始化的所有元素;即存在终止条件。你认为这是合法的使用吗?它似乎并不违反合同,尽管我想有人可能会说这是不直观的。hasNext()Iterator

public class CyclicIterator<T> implements Iterator<T> {
  private final List<T> l;
  private Iterator<T> it;

  public CyclicIterator<T>(List<T> l) {
    this.l = l;
    this.it = l.iterator();
  }

  public boolean hasNext() {
    return !l.isEmpty();
  }

  public T next() {
    T ret;

    if (!hasNext()) {
      throw new NoSuchElementException();
    } else if (it.hasNext()) {
      ret = it.next();
    } else {
      it = l.iterator();
      ret = it.next();
    }

    return ret;
  }

  public void remove() {
    it.remove();
  }
}

(迂腐)编辑

有些人评论了如何使用 an 从无界序列(如斐波那契数列)生成值。但是,Java 文档指出迭代器是:IteratorIterator

集合上的迭代器。

现在你可以争辩说斐波那契数列是一个无限的集合,但在Java中,我将集合等同于接口,它提供了诸如暗示集合必须有界等方法。因此,用作无界序列中的值的生成器是否合法?java.util.Collectionsize()Iterator


答案 1

我认为这是完全合法的 - 一个只是一个“东西”流。为什么流必须有边界?Iterator

许多其他语言(例如Scala)都有内置的无限流的概念,这些可以迭代。例如,使用 scalaz

scala> val fibs = (0, 1).iterate[Stream](t2 => t2._2 -> (t2._1 + t2._2)).map(_._1).iterator
fibs: Iterator[Int] = non-empty iterator

scala> fibs.take(10).mkString(", ") //first 10 fibonnacci numbers
res0: String = 0, 1, 1, 2, 3, 5, 8, 13, 21, 34

编辑:就最小惊喜原则而言,我认为这完全取决于上下文。例如,我希望此方法返回什么?

public Iterator<Integer> fibonacciSequence();

答案 2

重点是它是懒惰的,即它只给你尽可能多的对象,只要你要求。如果用户要求无限的所有对象,这是他们的问题,而不是你的问题。IteratorIterator