Меня спросили об этом на интервью, и я не уверен, что дал лучший ответ, который мог дать. Я упоминал, что вы можете выполнять параллельный поиск и что нулевые значения обрабатывались каким-то способом, который я не мог вспомнить. Теперь я понимаю, что думал о Optionals. Что мне здесь не хватает? Они утверждают, что это лучший или более сжатый код, но я не уверен, что согласен.
Учитывая, насколько кратко на него был дан ответ, кажется, что это был не слишком широкий вопрос.
Если они задают этот вопрос на собеседовании, а они явно задают этот вопрос, какой цели может служить его разбивка, кроме как затруднить поиск ответа? Я имею в виду, что ты ищешь? Я мог бы разбить вопрос и получить ответы на все подвопросы, но затем создать родительский вопрос со ссылками на все подвопросы ... хотя это кажется довольно глупым. Пока мы занимаемся этим, приведите, пожалуйста, мне пример менее широкого вопроса. Я не знаю, как задать только часть этого вопроса и все же получить содержательный ответ. Я мог бы задать точно такой же вопрос по-другому. Например, я мог бы спросить «Какую цель служат потоки?» или "Когда я буду использовать поток вместо цикла for?" или "Зачем беспокоиться о потоках, а не о циклах?" Но это все тот же вопрос.
... или это считается слишком широким, потому что кто-то дал действительно длинный многоточечный ответ? Откровенно говоря, любой знающий мог сделать это практически с любым вопросом. Если, например, вы являетесь одним из авторов JVM, вы, вероятно, могли бы говорить о циклах for весь день, в то время как большинство из нас не могли.
«Пожалуйста, отредактируйте вопрос, чтобы ограничить его конкретной проблемой с достаточной детализацией, чтобы найти адекватный ответ. Не задавайте сразу несколько разных вопросов. См. Страницу Как задать вопрос, чтобы прояснить этот вопрос».
Как отмечено ниже, был дан адекватный ответ, который доказывает, что он существует и что его достаточно легко дать.
источник
Ответы:
Интересно, что вопрос интервью спрашивает о преимуществах, не спрашивая о недостатках, поскольку есть и то, и другое.
Потоки - это более декларативный стиль . Или более выразительный стиль. Может показаться, что лучше заявить о своем намерении в коде, чем описывать, как это делается:
... совершенно ясно говорит, что вы фильтруете совпадающие элементы из списка, тогда как:
Говорит «делаю петлю». Цель цикла глубже закопана в логике.
Потоки часто более краткие . Тот же пример показывает это. Тессер не всегда лучше, но если вы можете быть лаконичным и выразительным одновременно, тем лучше.
Потоки очень похожи на функции . В Java 8 представлены лямбда-выражения и функциональные интерфейсы, что открывает целый набор мощных методов. Потоки предоставляют наиболее удобный и естественный способ применения функций к последовательностям объектов.
Потоки способствуют меньшей изменчивости . Это как бы связано с аспектом функционального программирования - программы, которые вы пишете с использованием потоков, обычно относятся к тем программам, в которых вы не изменяете объекты.
Потоки способствуют ослаблению связи . Вашему коду обработки потока не обязательно знать источник потока или его возможный метод завершения.
Потоки могут лаконично выражать довольно сложное поведение . Например:
На первый взгляд может показаться, что он фильтрует весь поток, а затем возвращает первый элемент. Но на самом деле
findFirst()
управляет всей операцией, поэтому она эффективно останавливается после нахождения одного элемента.Потоки предоставляют возможности для повышения эффективности в будущем . Некоторые люди провели тестирование и обнаружили, что однопоточные потоки из in-memory
List
s или массивов могут быть медленнее, чем эквивалентный цикл. Это правдоподобно, потому что в игре больше объектов и накладных расходов.Но потоки масштабные. Помимо встроенной поддержки Java для параллельных потоковых операций, существует несколько библиотек для распределенного сокращения карты с использованием Streams в качестве API, потому что модель подходит.
Недостатки?
Производительность :
for
цикл через массив чрезвычайно легок с точки зрения использования кучи и ЦП. Если приоритетом является чистая скорость и бережливость памяти, использование потока хуже.Знакомство . В мире полно опытных процедурных программистов, владеющих разными языками, для которых циклы знакомы, а потоки - в новинку. В некоторых средах вы захотите написать код, знакомый таким людям.
Когнитивные накладные расходы . Из-за его декларативного характера и повышенной абстракции от того, что происходит внутри, вам может потребоваться построить новую мысленную модель того, как код соотносится с выполнением. На самом деле вам нужно делать это только тогда, когда что-то идет не так, или если вам нужно глубоко проанализировать производительность или малозаметные ошибки. Когда он «просто работает», он просто работает.
Отладчики улучшаются, но даже сейчас, когда вы проходите через потоковый код в отладчике, это может быть труднее, чем эквивалентный цикл, потому что простой цикл очень близок к переменным и местоположениям кода, с которыми работает традиционный отладчик.
источник
Помимо синтаксического удовольствия, Streams предназначены для работы с потенциально бесконечно большими наборами данных, тогда как массивы, коллекции и почти каждый класс Java SE, который реализует Iterable, полностью находятся в памяти.
Недостатком Stream является то, что фильтры, сопоставления и т. Д. Не могут генерировать проверенные исключения. Это делает Stream плохим выбором, скажем, для промежуточных операций ввода-вывода.
источник
Stream<Row>
- или можно было бы написать собственнуюStream
реализацию, оборачивающую операции курсора результата БД.Arrays.asList("test", null).stream().forEach(s -> System.out.println(s.length()));
Вы неправильно поняли: параллельные операции используют
Stream
s, а неOptional
s.Вы можете определить методы, работающие с потоками: принимать их как параметры, возвращать их и т. Д. Вы не можете определить метод, который принимает цикл как параметр. Это позволяет выполнять сложную потоковую операцию один раз и использовать ее много раз. Обратите внимание, что у Java здесь есть недостаток: ваши методы должны вызываться, а
someMethod(stream)
не собственные потокиstream.someMethod()
, поэтому их смешивание усложняет чтение: попробуйте увидеть порядок операций вМногие другие языки (C #, Kotlin, Scala и т. Д.) Допускают некоторую форму «методов расширения».
Даже если вам нужны только последовательные операции и вы не хотите их повторно использовать, чтобы можно было использовать потоки или циклы, простые операции с потоками могут соответствовать довольно сложным изменениям в циклах.
источник
Optional
является альтернативойnull
, но не имеет ничего общего с параллельными операциями. Если в вашем вопросе «Теперь я понимаю, что я думал о Optionals» речь идет только обnull
обработке?Вы перебираете последовательность (массив, коллекция, ввод, ...), потому что хотите применить некоторую функцию к элементам последовательности.
Потоки дают вам возможность составлять функции по элементам последовательности и позволяют реализовать наиболее общие функции (например, отображение, фильтрацию, поиск, сортировку, сбор и т. Д.) Независимо от конкретного случая.
Поэтому, учитывая некоторую задачу цикла, в большинстве случаев вы можете выразить ее с меньшим количеством кода с помощью потоков, то есть вы получите удобочитаемость .
источник
Я бы сказал, что его распараллеливание настолько простое в использовании. Попробуйте перебрать миллионы записей параллельно с циклом for. Мы переходим на многие процессоры, но не быстрее; так что чем проще будет работать параллельно, тем лучше, а с
Stream
s это проще простого .Что мне очень нравится, так это их многословие . Требуется немного времени, чтобы понять, что они на самом деле делают и производят, а не то, как они это делают.
источник