1. ホーム
  2. java

[解決済み] コレクションとストリームのどちらを返すべきですか?

2022-04-20 01:13:39

質問

メンバーリストへの読み取り専用ビューを返すメソッドがあるとします。

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ではストリームを返すことは非日常的なことなのでしょうか?ストリームは常に、作成されたのと同じ式の内部で "terminate"されるように設計されていたのでしょうか?

解決方法は?

答えは、いつものように、quot;it depends"です。 返されるコレクションがどれくらいの大きさになるかによります。 結果が時間とともに変化するかどうか、また、返される結果の一貫性がどれほど重要であるかによります。 そして、ユーザーがその答えをどのように使用するかに大きく依存します。

まず、注意点として、常に Collection から 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 はすでにこれらを内蔵しており、コレクションを実体化する必要はありません (特に、ユーザーが結果全体を処理しない可能性がある場合)。 これは非常によくあるケースです。

ユーザーが何度も反復したり、そうでなくともそれを維持することが分かっていても、やはり Stream その理由は、どのような Collection を選択し、それを入れる(例. ArrayList ) が、彼らの望む形でない可能性があり、その場合、呼び出し側はとにかくそれをコピーしなければならない。 もしあなたが Stream を行うことができます。 collect(toCollection(factory)) を、思い通りの形で手に入れることができます。

上記の "preferは Stream という事実からきています。 Stream の方がより柔軟性があります。 Collection .

を返さなければならないケースは Collection は、強い一貫性の要求があり、移動するターゲットの一貫したスナップショットを作成する必要がある場合です。 その場合、要素を変更されないようにコレクションに格納する必要があります。

だから、たいていの場合はそうだと言えるでしょう。 Stream より柔軟性があり、通常不要なマテリアライゼーション・コストがかからず、必要に応じて簡単に好きなコレクションに変更することができます。 しかし、時には Collection (例えば、強い一貫性要求のため)、あるいは Collection というのも、ユーザーがどのように使うか知っていて、これが一番便利だとわかっているからです。

すでに適切な Collection として扱うほうがよさそうです。 Collection であれば、今あるものをそのまま返すというのは合理的な選択です(ただし、唯一の選択ではなく、よりもろいものです)。