Статьи

Java 8 MOOC – Сессия 3 Подведение итогов

Прошлая ночь была последней встречей, чтобы обсудить  Java 8 MOOC . Любое мероприятие, проводимое в августе в городе, температура которого постоянно превышает 40 ° C, столкнется с трудностями, поэтому было здорово, что у нас были посетители с предыдущих сессий, а также новые люди.

Woohoo лямбды!

Целью этого занятия было рассказать об уроке 3, а также подвести итоги курса в целом: рассказать о том, что нам понравилось и что мы могли бы улучшить (как о самом курсе, так и о событиях в нашей группе пользователей).

Как и в предыдущих  двух  постах , давайте наметим наши области обсуждения:

findAny ()  против  findFirst () : зачем нам нужны оба этих метода и когда вы их используете?

Ну,  findFirst() это детерминированная версия, которая вернет вам первый элемент в потоке (в соответствии с порядком встреч — см. Раздел «Порядок»  в документации ). Таким образом, независимо от того, выполняете ли вы операцию параллельно или последовательно, если вы ищете «A» и используете  findFirst с этим списком:

["B", "Z", "C", "A", "L", "K", "A", "H"]

Вы получите элемент с индексом 3 — первое «А» в списке.

Но  findAny() он недетерминирован, поэтому вернет вам любой элемент, который соответствует вашим критериям — он может вернуть элемент с индексом 3 или элемент с позицией 6. Реально, если поток находится в упорядоченной коллекции, такой как список, при запуске  findAny в последовательном потоке, я ожидаю, что он вернет тот же результат, что и  findFirst. Реальный вариант использования  findAny — когда вы запускаете это в параллельном потоке. Давайте возьмем приведенный выше список и предположим, что когда вы запускаете его в параллельном потоке, он обрабатывается двумя отдельными потоками:

["B", "Z", "C", "A",    // processed by thread 1 
 "L", "K", "A", "H"]     // processed by thread 2

Возможно, что поток 2 найдет свое «A» (тот, что в позиции 6), прежде чем поток 1 найдет его в позиции 3, так что это будет возвращаемое значение. Сконфигурировав Stream для возврата любого из значений, соответствующих критериям, вы можете потенциально выполнить операцию быстрее при параллельном запуске.

Если  findAny параллельно (возможно) быстрее и (вероятно) возвращает то же значение, что и  findFirst при работе в последовательном режиме, почему бы не использовать это все время? Ну, бывают моменты, когда вы действительно хотите первый элемент. Если у вас есть список DVD-дисков, упорядоченных по годам выпуска фильма, и вы хотите найти оригинальный «Кинг-Конг» (например), вам нужно  findFirstбудет найти тот, который был выпущен в 1933 году, а не тот, который был выпущен в 1976 или тот из 2005.

Плюс,  findFirst не всегда будет медленнее, чем  findAnyдаже параллельно. Возвращаясь к нашему списку:

["B", "Z", "C", "A", "L", "K", "A", "H"]

Попытка  findFirst или  findAny для «H» может быть одинаковой производительности для обоих методов

Коллекционеры : Может быть, только я не вижу общей картины для коллекционеров. Я отлично доволен встроенными коллекционерами, такими как:

collect(Collectors.toList())

и

collect(Collectors.toSet())

Легко увидеть, что они делают, и потренироваться, когда вам нужно их использовать.

Я также очень рад, что обнаружил  joining:

collect(Collectors.joining(","))

супер-полезный способ создания значений, разделенных запятыми (CSV), которые я использую в своей  демонстрации Java 8 .

Где все становится немного мрачно для меня, это когда мы начинаем цеплять коллекционеров:

collect(Collectors.mapping(...).combiner().andThen(...).apply(...))

(из моего отсутствия четкого примера должно быть очевидно, что я не уверен на 100%, при каких обстоятельствах они полезны).

Как группа, мы думаем, что цепочечные коллекторы выглядят некрасиво — не потому, что мы против цепочки (нам нравится Streams), а, может быть, потому, что это другая цепочка внутри параметра в цепочке.

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

В связи с этим курс вообще не создавал собственных коллекционеров. Мое личное (недостаточно информированное) мнение заключается в том, что я думаю, что большинство разработчиков должны иметь возможность использовать либо готовые коллекторы (и toList т. Д.), Либо использовать цепочку коллекторов для создания того, что им нужно. Если вам нужен пользовательский сборщик, возможно, вы не учли все, что вам уже доступно. Но, как группа, мы решили, что в любом случае хотели бы увидеть эту тему, чтобы глубже понять, что такое коллекционеры и как они работают.

Упражнения для урока 3:  Хорошо. Что мы можем сказать? Я действительно надеюсь, что есть люди, читающие это, которые еще не закончили курс, потому что группа пользователей Java в Севилье хотела бы сказать вам: не отчаивайтесь, упражнения на уроке 3  значительно  сложнее, чем на уроках 1 и 2. Честно говоря, вся группа считала, что это не просто кривая обучения, а большая скала для лазания.

Я понятия не имею, что я делаю

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

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

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

Для получения дополнительной информации
я собираюсь добавить бесстыдную заглушку в книгу друга здесь. Я много читал о Java 8 для этого курса, для моей  демонстрации Java 8 , и в целом, чтобы набрать скорость. Моя любимая книга о том, как разобраться с лямбдами и потоками, — это  Java 8 Lambdas: прагматическое функциональное программирование. Эта книга также содержит больше информации о сборщиках, поэтому, возможно, на некоторые из наших вопросов о том, как использовать их в более сложной ситуации, можно найти здесь.

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

Если / когда Oracle повторно запустит MOOC, если у вас не было возможности принять участие в этот раз, я настоятельно рекомендую зарегистрироваться. И если вы можете найти (или запустить) местную встречу, чтобы обсудить ее, это сделает этот опыт гораздо более увлекательным.