Реализовать фрейм для упрощенного Stream API, но использовать Builder

#java #builder

#java #Конструктор

Вопрос:

Есть задача, в которой нужно завершить класс. Я не совсем понимаю, как можно использовать шаблон Builder здесь?(Если бы это были поля класса, ну, понятно, но с методами это не работает, я не понимаю (ребята с опытом, можете мне помочь, пожалуйста) Есть некоторые условия:

  1. Реализовать фрейм для упрощенного Stream API.
  2. BestStream работает только с целочисленным типом.
  3. И нужно использовать pattern Builder.
  • Метод — исходные данные.
  • Метод map — преобразует число в другое число (элемент * 2).
  • Метод filter — фильтрует поток элементов (элемент == 2).
  • Метод collect — собирает все элементы из источника в соответствии с указанными условиями отображения и фильтрации.
 import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
    
public class BestStream {
    public static BestStream of(List<Integer> source) {
        throw new UnsupportedOperationException();
    }
    
    public BestStream map(Function<Integer, Integer> fun) {
        throw new UnsupportedOperationException();
    }
    
    public BestStream filter(Predicate<Integer> fun) {
        throw new UnsupportedOperationException();
    }
    
    public List<Integer> collect() {
        throw new UnsupportedOperationException();
    }
}
  

Ответ №1:

Я думаю, что поля в вашем случае являются «функциональными функциями» (функция и предикат), как вы можете заметить, они передаются в качестве параметра вашему методу.

В этом представлении вы можете применить builder, в котором вы можете «построить» поток, который работает в этом порядке:

  1. сопоставляет число с полем map
  2. фильтровать их по полю фильтра
  3. создать коллекцию в качестве результата

Пример:

 private static class BestStream {
    private final Stream<Integer> source;
    private Function<Integer, Integer> map;
    private Predicate<Integer> filter;

    private BestStream(Stream<Integer> source) {
        this.source = source;
    }

    public static BestStream of(List<Integer> source) {
        return new BestStream(source.stream());
    }

    public static void main(String[] args) {
        final List<Integer> collect =
                BestStream.of(Arrays.asList(1, 2, 3, 4, 2, 2, 9))
                        .filter(i -> Objects.equals(i, 2))
                        .map(i -> i * 2)
                        .collect();
    }

    public BestStream map(Function<Integer, Integer> fun) {
        this.map = fun;
        return this;
    }

    public BestStream filter(Predicate<Integer> fun) {
        this.filter = fun;
        return this;
    }

    public List<Integer> collect() {
        return source.map(map).filter(filter).collect(Collectors.toList());
    }
}
  

Комментарии:

1. После вашего решения я понял, как это работает! Вам тоже спасибо)

2. Если вы найдете ответ правильным и полезным, не могли бы вы установить его как принятый?

3. Если не использовать методы Stream API в последнем методе collect, но создать собственный?

Ответ №2:

Я думаю, что самый простой способ решить эту проблему — разбить ее на несколько классов.

Во-первых, пользователи интерфейса вашего API видят:

 package example;

import java.util.List;
import java.util.function.IntPredicate;
import java.util.function.IntUnaryOperator;

public interface BestStream {

    static BestStream of(List<Integer> list) {
        return new BestStreamListSource(list);
    }

    BestStream filter(IntPredicate predicate);
    BestStream map(IntUnaryOperator operator);
    List<Integer> collect();
}
  

во-вторых, интерфейс для внутренних целей:

 package example;

public interface BestStreamSource extends BestStream {

    Integer next();
}

  

Теперь базовая реализация вашего внутреннего BestStreamSource интерфейса, которая позже используется фактическими реализациями:

 package example;

import java.util.ArrayList;
import java.util.List;
import java.util.function.IntPredicate;
import java.util.function.IntUnaryOperator;

public abstract class BaseBestStreamSource implements BestStreamSource {

    @Override
    public BestStream filter(IntPredicate predicate) {
        return new BestStreamFilteredSource(this, predicate);
    }

    @Override
    public BestStream map(IntUnaryOperator operator) {
        return new BestStreamMappingSource(this, operator);
    }

    @Override
    public List<Integer> collect() {
        final List<Integer> result = new ArrayList<>();
        Integer value = null;

        while ((value = next()) != null) {
            result.add(value);
        }

        return resu<
    }
}

  

Теперь у вас есть 3 класса, которые на самом деле выполняют работу:

  • Один источник, считывающий элементы из списка
  • Тот, который выполняет фильтрацию на основе любого источника
  • Тот, который выполняет сопоставление на основе любого источника
 package example;

import java.util.List;
import java.util.Objects;

public class BestStreamListSource extends BaseBestStreamSource {

    private final List<Integer> list;
    private int index;

    public BestStreamListSource(List<Integer> list) {
        this.list = Objects.requireNonNull(list);
        this.index = 0;
    }

    @Override
    public Integer next() {
        if (this.index < this.list.size()) {
            return this.list.get(this.index  );
        } else {
            return null;
        }
    }
}
  
 package example;

import java.util.Objects;
import java.util.function.IntPredicate;

public class BestStreamFilteredSource extends BaseBestStreamSource {

    private final BestStreamSource parent;
    private final IntPredicate predicate;

    public BestStreamFilteredSource(BestStreamSource parent, IntPredicate predicate) {
        this.parent = Objects.requireNonNull(parent);
        this.predicate = Objects.requireNonNull(predicate);
    }

    @Override
    public Integer next() {
        final int[] holder = new int[1];
        Integer value = null;
        boolean foundMatch = false;

        while (!foundMatch amp;amp; (value = this.parent.next()) != null) {
            foundMatch = this.predicate.test(value);
        }

        if (foundMatch) {
            return value;
        } else {
            return null;
        }
    }
}

  
 package example;

import java.util.Objects;
import java.util.function.IntUnaryOperator;

public class BestStreamMappingSource extends BaseBestStreamSource {

    private final BestStreamSource parent;
    private final IntUnaryOperator mapping;

    public BestStreamMappingSource(BestStreamSource parent, IntUnaryOperator mapping) {
        this.parent = Objects.requireNonNull(parent);
        this.mapping = Objects.requireNonNull(mapping);
    }

    @Override
    public Integer next() {
        Integer value = this.parent.next();
        if (value != null) {
            value = this.mapping.applyAsInt(value);
        }

        return value;
    }
}

  

С помощью этого вы можете связать любой фильтр и сопоставление, которые хотите выполнить

Комментарии:

1. Спасибо за решение, но пока слишком сложно для меня)