Подтвердить что ты не робот

Обработать нулевое значение с помощью Guava MapMaker/CacheBuilder

Я пытаюсь создать кеш с помощью MapMaker/CacheBuilder, но я не понимаю, как правильно обрабатывать нулевые значения.

 ConcurrentMap<Key, Graph> graphs = new MapMaker()
       .concurrencyLevel(4)
       .weakKeys()
       .maximumSize(10000)
       .expireAfterWrite(10, TimeUnit.MINUTES)
       .makeComputingMap(
           new Function<Key, Graph>() {
             public Graph apply(Key key) {
               return createExpensiveGraph(key);
             }
           });

Если метод createExpensiveGraph возвращает значение null, то генерируется исключение NullpointerException. Я не понимаю, почему ComputingConcurrentHashMap выбрасывает NPE вместо того, чтобы просто возвращать нулевое значение.

Как правильно справиться с этим? Просто поймайте NPE и вместо этого верните нуль? Я что-то пропустил?

4b9b3361

Ответ 1

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

Ответ на ваш вопрос критически зависит от того, что на самом деле означает "нулевое" значение в вашем приложении. Скорее всего, это означает, что "нет значения" для этого ключа, или "ничего нет". В этом случае, вероятно, лучше всего использовать Optional, перенося ненулевые значения с помощью Optional.of и используя Optional.absent() вместо null. Если вы должны превратить это в нулевое или ненулевое значение, вы можете использовать Optional.orNull().

Ответ 2

Обратите внимание, что даже в полной формулировке вашего вопроса все еще неясно, должно ли ваше намерение кэшировать это нулевое значение или нет. Независимо от того, решил ли CacheBuilder кэшировать нулевые значения или нет, это удивит многих пользователей, которые ожидали обратного. Еще раз, null создает неоднозначности (что лучше всего в!).

Итак, вот что вы делаете.

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

  • Вы хотите кэшировать нулевое значение? Затем следуйте совету Луи, чтобы использовать Optional<T>.

  • В противном случае кеш не выполнил свою задачу по вызову правильного значения для ключа, и соответствующий ответ должен вызвать исключение из вашего загрузчика кеша (непроверено, если это ошибка программиста, в противном случае - в противном случае). И это обеспечит поведение, которое вы хотите. Если вы выбрали исключенное исключение, убедитесь, что вы используете Cache.get, а не Cache.getUnchecked, с другой стороны.