Comments 28
В Guava на каждом методе c transform в JavaDoc написано, что transform создает View, а не новую коллекцию. В документации и примеры на это, и пояснения для чего так, и что делать если там нужна именно копия. Не читаем, осуждаем. ССЗБ? Да.

Второй пример — вообще смешно. Вы выделили жирным «then»часть предложения, но почему-то не «if» :)
Ваш случай подпадал под один вариант, а вы выбрали другой. И пишете, что документация плохая :)

PS; Вместо того, чтобы использовать коннекшн пул нулевого размера — может лучше его всё же полностью убрать? :)

PS2: Статью следовало бы назвать «Даже усли использовать хорошие библиотеки, вы всё равно можете выстрелить себе в ногу» :)
В Guava на каждом методе c transform в JavaDoc написано, что transform создает View, а не новую коллекцию. В документации и примеры на это, и пояснения для чего так, и что делать если там нужна именно копия.

Да, написано, но абсолютно неочевидно из сигнатуры метода, в результате чего такая ошибка мне встречалась крайне часто (причём и у опытных людей). Мораль в результате именно такая: не верь тому, как оно выглядит, обязательно понимай как работает.
Не читаем, осуждаем. ССЗБ? Да.

Читаем, обсуждаем, передаём опыт будущим поколениям.

Второй пример — вообще смешно. Вы выделили жирным «then»часть предложения, но почему-то не «if» :)

Потому что после then написан ещё пример, когда это условие верно — при связи между AppEngine и CloudSQL.
Ваш случай подпадал под один вариант, а вы выбрали другой. И пишете, что документация плохая :)

Почему Вы так считаете? Скорость открытия соединения в описываемом случае действительно мала, так что проект подпадал как раз под этот вариант.

PS; Вместо того, чтобы использовать коннекшн пул нулевого размера — может лучше его всё же полностью убрать? :)

Не могли бы Вы объяснить, что Вы имеете ввиду? Пулл нулевого размера — это и есть дефакто отсутствие пулинга. (если просто убрать настройку пулинга, то будет использоваться default value 1 и это как раз то, что делать совсем не стоит).

PS2: Статью следовало бы назвать «Даже усли использовать хорошие библиотеки, вы всё равно можете выстрелить себе в ногу» :)

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

Получается «я книжку не читал, но она мне не понравилась». Если не читать документацию, а опираться на сигнатуры методов, то это уже не программирование/освоение библиотеки, а метод тыка в поисках «вроде бы работающего кода».
Не могли бы Вы объяснить, что Вы имеете ввиду? Пулл нулевого размера — это и есть дефакто отсутствие пулинга. (если просто убрать настройку пулинга, то будет использоваться default value 1 и это как раз то, что делать совсем не стоит).
Я подразумевал, что отключенный пуллинг и пул нулевого размера — не одно и тоже. Во втором случае остается оверхэд на оборачивание всех вспомогательных JDBC объектов в прокси пула.

Просмотрел бегло актуальные доки — судя по всему, со времен отделения c3p0 от самого Hibernate, hibernate.connection.pool_size со значением 0 именно отключает встроенный пул и вроде бы действительно отключает все дополнительные механизмы, нужные для пуллинга.
> Потому что после then написан ещё пример, когда это условие верно — при связи между AppEngine и CloudSQL.

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

> The key words «MUST», «MUST NOT», «REQUIRED», «SHALL», «SHALL
> NOT», «SHOULD», «SHOULD NOT», «RECOMMENDED», «MAY», and
> «OPTIONAL» in this document are to be interpreted as described in
> RFC 2119.
> www.ietf.org/rfc/rfc2119.txt
Это инструкции для IETF. При написании документации к cloud sql им следовать, вообще говоря, не обязаны.

В данном случае имеет место рекомендация (и условие действительно выполняется).
Вообще говоря, не обязаны, но в данном случае описание «may» более, чем подходит для выбранной цитаты. Даже дословный перевод это «может», а не «должен».

Рекомендации на то и рекомендации, что не обязательны к исполнению.

Я покидаю дискуссию, поскольку далее мы только будем толочь воду в ступе.

Спасибо.

P.S.: не поймите неправильно, я бы тоже ругался, что документация порекомендовала и рекомендация привела к неожиданным результатам, но на меня мои доводы подейстовали бы (как-то была похожая ситуция) :)
Это же восьмая Java? тогда почему не так?
    @Override
    public ImmutableList<Entity> getCheckedEntityByIds(List<Integer> ids) {
        logger.info("Received " + ids.size() + " ids.");
        Collection<Entity> filteredEntities = ids.stream()
                .map(id -> storageService.lookupEntity(id))
                .filter(Entity::performCheck)
                .collect(Collectors.toCollection());

        notificationService.sendUpdate(filteredEntities.stream()
                .map(Entity::getId)
                .collect(Collectors.toCollection()));

        logger.info("Got " + filteredEntities.size() + " entities.");
        return ImmutableList.copyOf(filteredEntities);
    }
Потому что тогда бы этой истории не было бы — stream api действительно имеет более предсказуемое поведение, хотя и работает в среднем медленнее guava (в случае завершающего копирования).

Сам пример, очевидно, от версии Java слабо зависит. Писался на 8й для краткости исходного кода.
stream api действительно имеет более предсказуемое поведение, хотя и работает в среднем медленнее guava (в случае завершающего копирования)

А можно пруфы? =/
Collectors.toCollection() без аргумента не бывает. Тогда уж Collectors.toList(). Но вообще стрим действительно продуманнее. Тут есть явная разница между коллекцией и потоком данных, одно с другим не спутаешь.
Если исключить то, что вы до конца не разобрались в исходных доках, то я бы обратил внимание на следующую мысль. Красивый код — не самоцель, он ещё и работать должен. Врёт не красивый код, а код, который, эм… собственно врёт.
Что-то я не понимаю. При автоматическом обрыве выполнения кода должны быть закрыты все используемые ресурсы, в том числе соединение с БД. Закрытие соединения с БД должно остановить все выполняемые запросы.

Если в этом механизме что-то поломалось, то при чем тут пулы соединений?
При автоматическом обрыве запроса обрывается выполнение этого запроса. В случае, если запрос был «убит» это может вызвать повисший запрос, который конечно откатится, но уже спустя некоторое время.
Пулы соединений как раз гарантируют, к примеру, что один инстанс не будет открывать слишком много соединений.
Что такое «обрыв выполнения»? Если это Thread.stop — то он возбуждает ошибку ThreadDeath, которая приводит, в том числе, к выполнению finally-блоков.

Если всюду где надо использовать примитивы вроде try-with-resources, и при этом не выполнять работы в конструкторах — то все запросы должны нормально отмениться.
Кем?! JVM не может убиваться по тайм-ауту запроса HTTP — просто потому что никто не будет запускать по JVM на запрос.
C Guava я бы написал так. Итого 1 итерация.
    @Override
    public ImmutableList<Entity> getCheckedEntityByIds(List<Integer> ids) {
        logger.info("Received " + ids.size() + " ids.");

        ImmutableList<Entity> result = FluentIterable
                .from(ids)
                .transform(lookupFunction)
                .filter(checkPredicate)
                .transform(mapToIdFunction)
                .toList();

        logger.info("Got " + result.size() + " entities.");
        return result;
    }

неа
там в нотификейшн айдишники идут, а в результат — полноценные объекты
Логично. Убрать transform(mapToIdFunction) и вынести логику notificationService на уровень выше нужно. Ибо с названием метода данный call никак не связан.
на уровень выше не получится — в него отправляются не все айдишники со входа, а только отфильтрованные
Only those users with full accounts are able to leave comments. Log in, please.