La réponse est, comme toujours, "ça dépend". Cela dépend de la taille de la collection retournée. Cela dépend de l'évolution du résultat dans le temps et de l'importance de la cohérence du résultat renvoyé. Et cela dépend beaucoup de la manière dont l'utilisateur est susceptible d'utiliser la réponse.
Tout d'abord, notez que vous pouvez toujours obtenir une collection à partir d'un flux, et vice versa:
// If API returns Collection, convert with stream()
getFoo().stream()...
// If API returns Stream, use collect()
Collection<T> c = getFooStream().collect(toList());
La question est donc de savoir ce qui est plus utile pour vos appelants.
Si votre résultat peut être infini, il n'y a qu'un seul choix: Stream.
Si votre résultat peut être très volumineux, vous préférez probablement Stream, car il peut ne pas être utile de tout matérialiser en même temps, ce qui pourrait créer une pression considérable sur le tas.
Si tout ce que l'appelant va faire est de le parcourir (recherche, filtre, agrégation), vous devriez préférer Stream, car Stream les a déjà intégrés et il n'est pas nécessaire de matérialiser une collection (surtout si l'utilisateur ne peut pas traiter le résultat global.) C'est un cas très courant.
Même si vous savez que l'utilisateur l'itérera plusieurs fois ou le gardera autrement, vous voudrez peut-être renvoyer un Stream à la place, pour le simple fait que quelle que soit la collection dans laquelle vous choisissez de la mettre (par exemple, ArrayList) peut ne pas être la forme qu'ils veulent, puis l'appelant doit le copier de toute façon. si vous renvoyez un flux, ils peuvent le faire collect(toCollection(factory))
et l'obtenir exactement sous la forme souhaitée.
Les cas ci-dessus "prefer Stream" découlent principalement du fait que Stream est plus flexible; vous pouvez vous lier tardivement à la façon dont vous l'utilisez sans encourir les coûts et les contraintes liés à sa matérialisation dans une collection.
Le seul cas où vous devez renvoyer une collection est lorsqu'il existe des exigences de cohérence fortes et que vous devez produire un instantané cohérent d'une cible en mouvement. Ensuite, vous voudrez mettre les éléments dans une collection qui ne changera pas.
Je dirais donc que la plupart du temps, Stream est la bonne réponse - il est plus flexible, il n'impose pas de coûts de matérialisation généralement inutiles et peut être facilement transformé en collection de votre choix si nécessaire. Mais parfois, vous devrez peut-être retourner une collection (par exemple, en raison de fortes exigences de cohérence), ou vous voudrez peut-être renvoyer une collection car vous savez comment l'utilisateur l'utilisera et savez que c'est la chose la plus pratique pour eux.
players.stream()
c'est une telle méthode qui renvoie un flux à l'appelant. La vraie question est la suivante: voulez-vous vraiment contraindre l'appelant à une traversée unique et lui refuser également l'accès à votre collection via l'Collection
API? Peut-être que l'appelant veut juste l'envoyeraddAll
à une autre collection?