使用来自不同类层次结构路由的两个字段进行map-filter lambda表达式

时间:2018-09-12 11:38:01

标签: java lambda java-8 optional

我们有一个方法,该方法在类层次结构的顶部接收该类的对象。它使用一个条件,该条件基于层次结构中某个较深层的字段,如果满足,则为构建器使用另一个条件,该字段也位于层次结构中某个较深层的位置,但从顶级类开始使用另一条路径。

public Optional<SomeType> create(final TopClassInHierarchy topClass) {
  Optional<SomeType> someObject = Optional.empty();
  if (someCondition.evaluate(getFieldOne(topClass))) {
      someObject = Optional.of(new SomeType.Builder()
              .withFieldTwo(getFieldTwo(topClass))
              .build());
  }
  return someObject;

private FieldOne getFieldOne(TopClassInHierarchy topClass) { return topClass.getSomething()...getFieldOne();
private FieldTwo getFieldTwo(TopClassInHierarchy topClass) { return topClass.getSomethingElse()...getFieldTwo();

我们希望将其简化为一个这样的语句

SomeType.Builder builder = new SomeType.Builder();
Optional.of(topClass)
        .map(this::getFieldOne)
        .filter(someCondition::evaluate)
        .map(this::getFieldTwo) //???
        .ifPresent(builder::withFieldTwo);

但是,一旦我们将topClass向下映射到fieldOne进行条件评估,此后,我们似乎就无法“退回”到topClass以将其向下映射到构建器的fieldTwo。一句话这可行吗?

3 个答案:

答案 0 :(得分:2)

你不能说类似的话吗

.map(x -> new SimpleEntry<>(this.getFieldOne(x), this.getFieldTwo(x)))
.filter(e -> evaluateTheCondition(e.getKey()))
.map(Entry::getValue)
.ifPresent(builder::withFieldTwo);

答案 1 :(得分:2)

由于不需要getFieldOne,因此不应该映射到它,否则就无法返回到另一个getFieldTwo的映射。我建议您先使用不带方法引用的过滤器,如果它的评估结果为true,则返回给getFieldTwo:

Optional.of(entity)
                .filter(p->someCondition.evaluate(p.getSomething().getFieldOne()))
                .map(this::getFieldTwo) 
                .ifPresent(builder::withFieldTwo);

答案 2 :(得分:2)

如果认为这可行:

public Optional<SomeType> create(final TopClassInHierarchy topClass) {
  Builder builder = new Builder();

  return Optional.of(topClass)
    .filter(tc -> someCondition.evaluate(getFieldOne(tc)))
    .map(tc -> builder.withFieldTwo(getFieldTwo(tc)).build());
}
someCondition.evaluate中的

filter需要fieldOne作为输入,但是要保持topClass作为Optional的当前状态,我们不需要mapfieldOne。而是使用方法getFieldOne。如果通过了过滤器,我们可以将topClass映射到通过方法builder检索的fieldTwo上应用的getFieldTwo的结果。

或具有更多中间映射:

public Optional<SomeType> create(final TopClassInHierarchy topClass) {
    Builder builder = new Builder();

    return Optional.of(topClass)
            .filter(tc -> someCondition.evaluate(getFieldOne(tc)))
            .map(this::getFieldTwo)
            .map(builder::withFieldTwo)
            .map(Builder::build);
}