Это плохая практика добавлять операции к потоку различными методами? - PullRequest
0 голосов
/ 21 ноября 2018

Предположим, у меня есть метод, используемый несколькими классами в моем приложении.Этот метод принимает Stream в качестве параметра и применяет терминальную операцию forEach для записи данных в файл, что-то вроде следующего:

public File writeStreamToTempFile(Stream stream) {
    stream.forEach(item -> {
        //some code to write item to a file
    }
}

Существует несколько абонентов этого метода,и в некоторых из этих методов мне нужно преобразовать данные, скажем, с помощью функции map, например:

public void exportAnimalsData() {
    Stream<Animal> animalStream = //fetch data from a DB
    animals.filter(a -> a.type.equals("dog"))
           .map(a -> //Do something useful to transform the Dogs);

    writeStreamToTempFile(animalStream);
}

Не всем вызывающим методам writeStreamToTempFile необходимо выполнять дополнительные операции в потоке.

Итак, мой вопрос:

Плохо ли применять операции к потоку различными методами?

Я где-то читал, что Stream никогда не должен возвращать тип метода (вызывающая сторона не знает, использует ли этот метод поток или нет), это также применимо к параметрам метода?

Должен ли я просто применить все операции, необходимые для одного и того же метода, или можно добавить промежуточные операции к одному и тому же потоку другим методом?

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

я где-то читал, что Stream никогда не должен быть типом возврата метода

Не уверен, где вы читаете, что Stream никогда не должно быть типом возврата метода.(Можете ли вы обновить свой вопрос со ссылкой?).

Наоборот, Брайан Гетц, один из разработчиков Stream API, явно думает иначе:

https://stackoverflow.com/a/24679745/340088

(звонящий не знаетесли этот метод уже использует поток или нет)

Если вызывающая сторона получает Stream, подразумевается, что поток пригоден для использования.Если вы возвращаете израсходованный Stream, это все равно что вернуть закрытый Socket или закрытый InputStream.Хотя это возможно синтаксически, это просто плохое кодирование.Это не значит, что вы не должны возвращать Socket или InputStream из метода только потому, что какой-то плохой кодер иногда возвращает его в плохом состоянии.

Напротив, объекты монадического стиля предназначены длябыть возвращенным.Stream, Optional, CompletableFuture и все функциональные интерфейсы (Function, Consumer, Operator и т. Д.) Предназначены для возврата, чтобы к ним можно было присоединить больше операций в функциональном стилебез фактического выполнения функции на месте.

Пример, который вы разместили для меня, вполне обоснован.Вы как бы украшаете свой Stream дополнительными операциями для конвейера.Вы можете иметь логику, которая решает, какие операции добавляются в конвейер, и нет никаких причин, почему бы не инкапсулировать их должным образом в маленькие методы.

Кроме того, если поток очень большой, содержащий сотни тысяч элементов, если вы вернете коллекцию, вы просто создадите огромную коллекцию в памяти, что повлечет за собой затраты на добавление их всех, а затем в поток.их снова, чтобы записать их в файл.Не имеет особого смысла, не так ли?

0 голосов
/ 21 ноября 2018

Должен ли я просто применить все операции, необходимые в одном и том же методе, или можно добавить промежуточные операции в один и тот же поток другим методом?

Технически это не обязательно одно и то жепоток / объект.Например, вызов операции, такой как map() в потоке, создаст другой поток.

На самом деле, я думаю, что хотя вы не использовали поток при терминальной операции, я не понимаю, почему было бы сложно работать над ним, чтобы создать или получить ожидаемый поток, а затем перейти кметод, который ожидает поток.

...