【问题标题】:Is it bad practice to return an iterable in a method?在方法中返回可迭代对象是不好的做法吗?
【发布时间】:2013-10-20 07:13:11
【问题描述】:

我经常在很多地方读到,应该避免返回iterable,而是返回collection。比如——

public Iterable<Maze> Portals() {     
    // a list of some maze configurations
    List<Maze> mazes = createMazes();
    ...
    return Collections.unmodifiableList(mazes);
}

由于返回 iterable 仅对在 foreach 循环中使用它有用,而 collection 已经提供了 iterator 并提供了更多控制。您能否告诉我什么时候在方法中专门返回 iterable 是有益的?或者我们应该总是返回collection

注意:这个问题与 Guava 库无关

【问题讨论】:

    标签: java collections iterator


    【解决方案1】:

    当我们需要延迟加载包含大量元素的集合时,返回 Iterable 会很有用。

    Google Collections FAQ 的以下引用似乎支持延迟加载的想法:

    为什么如此强调迭代器和可迭代对象?

    一般来说,我们的方法不需要传入一个 Collection 当一个 Iterable 或 Iterator 就足够了。这种区别是 对我们很重要,因为有时在 Google,我们与非常大 数据量,可能太大而无法放入内存,但 可以在一些过程中从头到尾遍历 计算。这样的数据结构可以实现为集合, 但是他们的大多数方法都必须抛出异常, 返回错误的答案,或执行得很糟糕。对于这些情况, 收藏品非常不合适;圆孔中的方钉。

    Iterator 表示一种单向可滚动的元素“流”,并且 Iterable 是可以产生独立迭代器的任何东西。一种 收藏远不止这些,所以我们只在我们需要时才需要它 需要。

    【讨论】:

      【解决方案2】:

      我可以看到优点和缺点:

      • 一个优点是Iterable 是一个比Collection 更简单的接口。如果你有一个非标准的集合类型,那么Iterable 可能比Collection 更容易。实际上,有些集合的某些Collection 方法难以实现。例如,惰性集合类型和您不想依赖标准 equals(Object) 方法来确定成员资格的集合。

      • 一个缺点是Iterable 功能很差。如果您有一个实现Collection 的具体类型,并将其作为Iterable 返回,那么您就消除了代码可以(直接)调用各种有用的收集方法的可能性。

      • 在某些情况下,Iterable 或 Collection 都不适合;例如原始类型的专业集合...您需要避免使用原始包装类型的开销。

      您不能说返回Iterable 是好还是坏。视情况而定;例如您正在设计的 API 的目的,以及您希望/需要对其施加的要求或约束。

      【讨论】:

        【解决方案3】:

        问题是,如果底层集合发生变化,你就会遇到麻烦。 如果您使用的集合会引发 concurrentmodification 异常,那么您也必须注意它,但集合不会出现此类问题。

        【讨论】:

        • 这没有任何意义。底层集合仍然是相同的实现,无论它是保存在 Iterable 还是 Collection 引用中。
        • @SimonC:假设我将一个可迭代对象返回给用户,他开始使用它来迭代集合,而在他迭代时其他一些用户更改了集合。用户将获得例外权利。现在有意义吗?
        • 我知道你想说什么,但如果正在修改的集合保存在类型为 Iterable 的变量中作为类型为 @987654325 的变量,则会发生完全相同的事情@。被修改的集合仍然是相同的具体类型。
        • @SimonC:我的观点是,如果你有收藏,那么你总是可以选择不使用迭代器进行遍历,因此可以避免并发修改异常。如果你传递迭代器,那么你别无选择。
        • 好的,我明白你的意思了。但是,ConcurrentModificationExceptions 表示编程错误。您不应该故意访问您知道可能会在没有某种同步的情况下被另一个线程修改的集合。使用Collection 上的方法访问正在被另一个线程修改的集合可能会避免抛出异常,但会产生不可预知的行为。
        【解决方案4】:

        返回对相关用途有意义的最具体的类型。例如,如果您有一个创建新集合的方法,或者您可以轻松地将集合包装在不可修改的包装器中,将集合返回为Collection,甚至是ListSet,使客户端开发人员的生活更轻松。

        返回Iterable 对可以即时生成值的代码有意义;例如,您可以想象一个斐波那契生成器,它创建了一个 Iterator 来计算下一个数字,而不是尝试存储一些查找表。如果您正在编写这样一种“流式”API 可能有用的框架或接口代码(Guava 及其函数类在这方面做得很好),那么指定 Iterable 而不是集合类型可能是值得的消费者方面的灵活性。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-05-07
          • 2020-11-13
          • 2019-09-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-29
          相关资源
          最近更新 更多