Использование двух полей из разных маршрутов иерархии классов для лямбда-выражения map-filter - PullRequest
0 голосов
/ 12 сентября 2018

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

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 голосов
/ 12 сентября 2018

Поскольку вам не нужен getFieldOne, вы не должны отображаться на него, иначе вы не сможете вернуться к карте для другого getFieldTwo; я предлагаю вам сначала использовать фильтр без ссылки на метод и, если он оценивается как истинная карта, получить getFieldTwo:

Optional.of(entity)
                .filter(p->someCondition.evaluate(p.getSomething().getFieldOne()))
                .map(this::getFieldTwo) 
                .ifPresent(builder::withFieldTwo);
0 голосов
/ 12 сентября 2018

Если считаете, что это должно работать:

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 до fieldOne.Вместо этого используется метод 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);
}
0 голосов
/ 12 сентября 2018

Если вы не можете сказать что-то вроде:

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