Java 8 извлекает ненулевое и не пустое значение из HashMap

Рассмотрим ниже HashMap

HashMap<String, String> map = new HashMap<String, String>();

У меня есть значения на карте, такие как

map.put("model", "test");

В настоящее время, если я хочу получить значение с карты, я делаю

if(map!=null){
 if(map.get("model")!=null && !map.get("model").isEmpty()){
   //some logic
 }
}

Есть ли лучший подход в Java 8 с помощью Optional или Lambdas для достижения вышеуказанного условия?

Ответ 1

Не уверен, почему вы проверяете, является ли карта нулевой, но здесь идет:

Optional.ofNullable(map)
    .map(m -> m.getOrDefault("model", "")) // Use an empty String if not present
    .filter(s -> !s.isEmpty())             // Filter all empty values
    .ifPresent(valueString -> {            // Check if value is present
        // Logic here
});

Или в одной строке:

Optional.ofNullable(map).map(m -> m.getOrDefault("model", "")).filter(s -> !s.isEmpty()).ifPresent(valueString -> {
        // Logic here
});

Измените ifPresent на map, если вы хотите что-то вернуть; то есть не зависит от того, что вы вычисляете.

Ответ 2

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

Теперь, к сожалению, у Java нет такого метода утилиты, но есть несколько общедоступных libs (apache commons, Guava и т.д.), или вы можете написать его самостоятельно, чтобы он стал:

String model = map.get("model");
if (!Strings.isEmptyOrNull(model)) {
    // do somthing
}

Использование необязательного для обнуления значения NULL как части вашей логики считается антипаттерном. Опция предназначена для использования в качестве типа возврата. Поэтому я бы не стал его использовать здесь.

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

Ответ 3

Если вас интересует Optional,

Вы можете обернуть значение map.get("model") в Optional.ofNullable и выполнить фильтрацию Predicate<String> value -> !value.isEmpty():

if (isNull(map)) { // import static java.util.Objects.isNull;
    return;        // to minimise nesting
}

Optional.ofNullable(map.get("model"))
        .filter(value -> !value.isEmpty())
        .ifPresent(value -> { ... });

Ответ 4

Если вы объявили map как показано в вашем примере кода, это не будет null, и вам не нужно его проверять. Если вы хотите убедиться, то добавьте утверждение:

assert map != null;

Учитывая, что вы тестируете пустые строки, можно использовать пустую строку по умолчанию, если ключ отсутствует:

if (!map.getOrDefault("model", "").isEmpty()) {
    ...
}

Мне кажется, что стыдно, что в map не добавлен метод, который возвращает Optional, а не null, если ключ отсутствует. Что-то вроде:

map.getOptional("model").filter(v -> !v.isEmpty()).ifPresent(v -> {
    ...
}

В то время как были добавлены дополнительные опции, было немного переработать старые API-интерфейсы, чтобы осудить методы, которые возвращают null, чтобы означать "нет".