代码之家  ›  专栏  ›  技术社区  ›  hammerfest

对映射筛选器lambda表达式使用来自不同类层次结构路由的两个字段

  •  3
  • hammerfest  · 技术社区  · 7 年前

    我们有一个方法,它在类层次结构的顶部接收类的对象。它使用一个基于层次结构中某个较深的字段的条件,如果满足了这个条件,那么它将为生成器使用另一个也在层次结构中某个较深的字段,但从顶级开始的路径不同。

    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以将其映射到field2以供构建器使用。一句话就行吗?

    3 回复  |  直到 7 年前
        1
  •  2
  •   LuCio    7 年前

    如果你认为这是可行的:

    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 我们没有 map . 取而代之的是方法 getFieldOne 已使用。如果过滤器通过,我们可以映射 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);
    }
    
        2
  •  2
  •   Eugene    7 年前

    你不应该说这样的话吗

    .map(x -> new SimpleEntry<>(this.getFieldOne(x), this.getFieldTwo(x)))
    .filter(e -> evaluateTheCondition(e.getKey()))
    .map(Entry::getValue)
    .ifPresent(builder::withFieldTwo);
    
        3
  •  2
  •   MohammadReza Alagheband    7 年前

    因为您不需要getFieldOne,所以不应该映射到它,否则您无法返回到另一个getFieldTwo的映射;我建议您首先使用不带方法引用的过滤器,如果它的计算结果为true,则映射到getFieldTwo:

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