假设我有一个方法可以将只读 View 返回到成员列表中:
class Team {
private List<Player> players = new ArrayList<>();
// ...
public List<Player> getPlayers() {
return Collections.unmodifiableList(players);
}
}
进一步假设客户端所做的所有事情都是立即对列表进行一次迭代。也许将玩家放入 JList 或其他东西中。客户端确实不存储对列表的引用以供以后检查!
鉴于这种常见情况,我应该返回一个流吗?
public Stream<Player> getPlayers() {
return players.stream();
}
或者在 Java 中返回一个非惯用的流?流是否设计为始终在创建它们的同一表达式中“终止”?
最佳答案
一如既往,答案是“视情况而定”。这取决于返回的集合有多大。这取决于结果是否随时间变化,以及返回结果的一致性有多重要。这在很大程度上取决于用户可能如何使用答案。
首先,请注意,您始终可以从 Stream
中获取 Collection
,反之亦然:
// If API returns Collection, convert with stream()
getFoo().stream()...
// If API returns Stream, use collect()
Collection<T> c = getFooStream().collect(toList());
所以问题是,哪个对您的来电者更有用。
如果您的结果可能是无限的,那么只有一个选择:Stream
。
如果您的结果可能非常大,您可能更喜欢 Stream
,因为一次将其全部实现可能没有任何值(value),而且这样做可能会产生巨大的堆压力。
如果调用者要做的只是遍历它(搜索、过滤、聚合),你应该更喜欢 Stream
,因为 Stream
已经内置了这些并且不需要具体化集合(特别是如果用户可能不会处理整个结果。)这是一种非常常见的情况。
即使您知道用户会多次迭代它或以其他方式保留它,您仍然可能希望返回一个 Stream
,因为无论 Collection您选择放入的
(例如,ArrayList
)可能不是他们想要的形式,然后调用者无论如何都必须复制它。如果您返回 Stream
,他们可以执行 collect(toCollection(factory))
并以他们想要的形式得到它。
上述“更喜欢Stream
”的情况大多源于Stream
更加灵活;您可以后期绑定(bind)到如何使用它,而不会产生将其具体化为 Collection
的成本和限制。
您必须返回 Collection
的一种情况是存在强一致性要求,并且您必须生成移动目标的一致快照。然后,您需要将元素放入一个不会更改的集合中。
所以我想说,在大多数情况下,Stream
是正确的答案——它更灵活,不会强加通常不必要的实现成本,并且可以轻松转换为 Collection如果需要,您可以选择。但有时,您可能必须返回 Collection
(例如,由于强一致性要求),或者您可能希望返回 Collection
,因为您知道用户将如何使用它并且知道这对他们来说是最方便的。
如果您已经有一个合适的 Collection
“闲置”,并且您的用户似乎更愿意将其作为 Collection
与之交互,那么这是合理的选择(虽然不是唯一的,而且更脆弱)只返回你所拥有的。
关于java - 我应该返回集合还是流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24676877/