Ответ, как всегда, «это зависит». Это зависит от того, насколько большой будет возвращенная коллекция. Это зависит от того, изменяется ли результат с течением времени, и насколько важна согласованность возвращаемого результата. И это очень сильно зависит от того, как пользователь может использовать ответ.
Во-первых, обратите внимание, что вы всегда можете получить коллекцию из потока, и наоборот:
// 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 вместо этого, потому что тот факт, что независимо от выбранной вами коллекции (например, ArrayList), может не быть форма, которую они хотят, и тогда звонящий должен все равно скопировать это. если вы вернете поток, они могут сделать collect(toCollection(factory))
и получить его именно в той форме, которую они хотят.
Вышеупомянутые случаи «предпочтения Stream» в основном происходят из-за того, что Stream более гибок; вы можете позднее связать с тем, как вы используете его, не неся при этом затрат и ограничений, связанных с его материализацией в Коллекцию.
Единственный случай, когда вы должны вернуть коллекцию, - это когда существуют строгие требования согласованности, и вы должны создать согласованный снимок движущейся цели. Затем вы захотите поместить элементы в коллекцию, которая не изменится.
Поэтому я бы сказал, что в большинстве случаев Stream является правильным ответом - он более гибкий, он не влечет за собой обычно ненужных затрат на материализацию и может быть легко превращен в коллекцию по вашему выбору, если это необходимо. Но иногда вам может понадобиться вернуть коллекцию (скажем, из-за строгих требований согласованности), или вы можете захотеть вернуть коллекцию, потому что вы знаете, как ее будет использовать пользователь, и знаете, что это наиболее удобно для них.
players.stream()
именно такой метод возвращает поток вызывающей стороне. Реальный вопрос в том, действительно ли вы хотите ограничить вызывающего абонента одним обходом, а также лишить его доступа к вашей коллекции черезCollection
API? Может, звонящий просто хочет, чтобыaddAll
он попал в другую коллекцию?