小编典典

我应该返回集合还是流?

all

假设我有一个方法可以将只读视图返回到成员列表中:

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 中返回非惯用流?流是否设计为始终在创建它们的同一表达式中“终止”?


阅读 68

收藏
2022-08-05

共1个答案

小编典典

与往常一样,答案是“视情况而定”。这取决于返回的集合有多大。这取决于结果是否随时间变化,以及返回结果的一致性有多重要。这在很大程度上取决于用户可能如何使用答案。

首先,请注意,您始终可以Collection从 a中获取 a Stream,反之亦然:

// If API returns Collection, convert with stream()
getFoo().stream()...

// If API returns Stream, use collect()
Collection<T> c = getFooStream().collect(toList());

所以问题是,这对你的来电者更有用。

如果您的结果可能是无限的,那么只有一种选择:Stream.

如果您的结果可能非常大,您可能更喜欢Stream,因为一次实现所有结果可能没有任何价值,这样做可能会产生巨大的堆压力。

如果调用者要做的只是遍历它(搜索、过滤、聚合),你应该更喜欢Stream,因为Stream这些已经内置并且不需要具体化集合(特别是如果用户可能不会处理整个结果.)
这是很常见的情况。

即使您知道用户会重复它多次或以其他方式保留它,您仍然可能希望返回
aStream代替,因为Collection您选择放入的任何内容(例如,ArrayList)可能不是他们想要的形式,然后调用者无论如何都必须复制它。如果您返回
a Stream,他们可以collect(toCollection(factory))按照他们想要的形式执行并获得它。

上述“首选Stream”案例大多源于Stream更灵活的事实;您可以后期绑定到如何使用它,而不会产生将其具体化为Collection.

必须返回 a 的一种情况Collection是存在强一致性要求,并且必须生成移动目标的一致快照。然后,您需要将元素放入一个不会更改的集合中。

所以我想说,在大多数情况下,这Stream是正确的答案——它更灵活,不会强加通常不必要的实现成本,并且可以在需要时轻松转换为您选择的集合。但有时,您可能必须返回一个Collection(例如,由于强一致性要求),或者您可能想要返回Collection,因为您知道用户将如何使用它并且知道这对他们来说是最方便的。

如果您已经有一个合适的Collection“躺着”,并且您的用户似乎更愿意将其作为Collection.

2022-08-05