2017-02-03 2 views
1

Как я могу упростить следующий код, используя lambda java8? Я новичок в лямбда и все еще изучаю.Как преобразовать код с помощью Lambda java8

public boolean isValuePresent(String id, Optional<String> value) { 
     ClassConfig config = configStorage.getConfig(); 
     Map<String, FeatureClass> map = config.getConfigMap(); 
     if (map.containsKey(id)) { 
      Set<String> set = map.get(id).getset(); 
      if (!set.isEmpty()) { 
       if (value.isPresent()) { 
        if (set.contains(value.get())) { 
         log.info(String.format("value present for id %s", id)); 
         return true; 
        } 
       } 
      } 
     } 
     return false; 
    } 
+0

Для начала создайте новую функцию для блока, если oyu've обнаружил, что вы вложили более двух операторов if. – awiebe

+0

Почему у вас есть опция «Необязательный » как метод ввода? Конечно, вы можете проверить, присутствует ли он заранее, и просто предположить, что «значение нет»? –

ответ

-1

Этот код работает для вас?

for(Map.Entry<String, String> entry : map.entrySet()) { 
    if(entry.getKey().equals(id)) { 
     if (value.isPresent() && entry.getValue().equals(value.get())) { 
      System.out.println(String.format("value present for id %s", id)); 
      return true; 
     } 
    } 
} 
return false; 

Я попробовал это один Aswell, но функции возвращают в лямбда не работает:/

map.forEach((key, mapValue) -> { 
     if(key.equals(id)) { 
      if (value.isPresent() && mapValue.equals(value.get())) { 
       System.out.println(String.format("value present for id %s", id)); 
       return true; //doesn't work -> Unexpected return value 
      } 
     } 
    }); 

EDIT: Я нашел способ сделать это ^^

return map.entrySet().stream().anyMatch(entry -> entry.getKey().equals(id) && value.isPresent() && entry.getValue().equals(value.get())); 
+0

Вы перебираете всю карту, ища значения, соответствующие предикату, который никогда не может вернуть true, если 'value.isPresent() == false'. –

+0

Вы прочитали его код? Его метод даже называется «isValuePresent». Это просто логично, что он хочет проверить value.isPresent() ... @MikhailProhhorov – patwis

+0

уверен.но он также имеет карту с потенциальной сложностью «O (1)» для поиска ключа и «Необязательный », где, если в опции нет значения, он должен логически немедленно вернуть значение false. Вместо этого ваше решение выполняет операции 'O (n)', особенно если нет значения. –

0

Вкратце - нет. Нет ничего плохого или сложного с этим кодом, который разрешимо с помощью lambdas per se. Что вам лучше делать, это посмотреть, что на самом деле делает этот код, и упростить его оттуда. Мой взгляд на него, если вы не можете изменить подпись isValuePresent, то сделать что-то вроде этого:

boolean isValuePresent(String id, Optional<String> option) { 
    if (!option.isPresent()) { // this already saves us loading the config if we've got no value to check against 
    return false; 
    } 
    FeatureClass features = configStorage.getConfig().getConfigMap().get(id); 
    if (features == null) { // replaces containsKey().get() with one call. It is hardly an improvement, just my stylistic choice 
    return false; 
    } 
    String value = option.get(); 
    if (features.getset().contains(value) { // we actually have no need to check if set is empty or not, we rather have it handle that itself 
    log.info(String.format("value present for id %s", id)); 
    return true; 
    } 
    return false; 
} 

Или, если вы можете изменить подписи, я считаю, что лучше иметь что-то вроде этого:

boolean isValuePresent(String id, String value) { 
    FeatureClass features = configStorage.getConfig().getConfigMap().get(id); 
    if (features == null) { 
    return false; 
    } 
    if (features.getset().contains(value)) { 
    log.info(<snip>); 
    return true; 
    } 
    return false; 
} 

И называть это так:

String id = loadId(); 
Optional<String> myValue = loadMyValue(id); 
return myValue.map(value -> Checker.isValuePresent(id, value)).orElse(false); 

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

Теперь о том, почему я решил не иметь Дополнительно в аргументе:

  1. Это обеспечивает большую гибкость для абонентов вашего метода. Если у них уже есть значение String, они не будут обязаны обертывать его бесполезным Optional перед вызовом вашего метода.
  2. Использование метода аргумента метода выглядит уродливым, потому что этот класс предназначен для использования в качестве возвращаемого значения и не предлагает много аргументов, кроме isPresent() и get(). Сравните это с хорошим количеством методов извлечения контролируемых значений, когда оно используется как возвращаемое значение (чтобы назвать несколько, orElse, orElseGet, map, flatMap и еще больше, чтобы прийти в Java 9).
  3. java.util.Optional не Serializable, что положит конец вызову вашего метода через удаленный интерфейс (это, конечно, подразумевает, что вы заботитесь о его вызове через удаленный интерфейс).
Смежные вопросы