如何使用Lambda java8转换代码

时间:2017-02-03 06:30:39

标签: lambda

如何使用lambda java8简化以下代码? 我是lambda的新手并且还在学习它。

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;
    }

3 个答案:

答案 0 :(得分:2)

您已经完成了外部循环,并想使用流API,这使我们能够专注于内部循环逻辑。

在流中,共有3个部分。一个是源,这里是map.keySet(),第二个是一系列中间操作,即filter(),map()等。所有操作都创建新流并且不更改源,第三个是终端操作,即forEach(), collect(),anyMatch(),allMatch()等...

流具有耗材和惰性执行属性。这意味着在我们使用任何终止操作之前,流尚未执行。而且一旦应用了终止运算符,流就已经消耗了,无法再消耗了。

boolean retval = map.keySet().stream()
         .filter(x -> x.equals(id))
         .filter(x -> !map.get(x).getset().isEmpty())
         .filter(x -> value.isPresent())
         .anyMatch(x -> map.get(x).getset().contains(value.get()));
来自Java8的

Collection API实现了流接口。 Map不是集合API的一部分,因此我们使用map.keySet()并应用stream()来获取集合。这成为了我们的来源。 过滤器运算采用任何布尔表达式,这里我们将映射键与id参数进行比较,并检查值param是否存在。 anyMatch是终止操作,如果map中的任何键都满足上述条件,则它将返回true。

答案 1 :(得分:0)

总之 - 没有。这个代码可以用lambdas本身解决,没有任何错误或复杂。你应该做的是检查这段代码实际上做了什么,并从那里简化它。 我接受它,如果你不能改变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);

正如你所看到的,没有lambda,因为没有lambdas - 在这里我们不需要改变我们的行为,这种方法中没有可能从外部插入的策略。

现在,关于为什么我选择在参数中没有Optional:

  1. 它为您的方法的调用者提供了更大的灵活性。如果它们已经具有值String形式,则在调用您的方法之前,不需要将它包装在无用的Optional中。
  2. 使用Optional作为方法参数类型看起来很丑陋,因为该类设计用作返回值,并且除isPresent()get()之外不提供更多参数类型。当它被用作返回值时,将其与大量受控值提取方法进行比较(仅举几例,orElseorElseGetmapflatMap甚至更多进入Java 9)。
  3. java.util.Optional不是Serializable,它结束了通过远程接口调用您的方法(当然,这意味着您关心通过远程接口调用它)。

答案 2 :(得分:-1)

此代码是否适合您?

ModelName.pluck(:sunday).inject(:|)

我也试过这个,但是在lambda中返回函数不能工作:/

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;

修改 我找到了办法^^

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
            }
        }
    });