#java #builder
#java #Конструктор
Вопрос:
Есть задача, в которой нужно завершить класс. Я не совсем понимаю, как можно использовать шаблон Builder здесь?(Если бы это были поля класса, ну, понятно, но с методами это не работает, я не понимаю (ребята с опытом, можете мне помочь, пожалуйста) Есть некоторые условия:
- Реализовать фрейм для упрощенного Stream API.
- BestStream работает только с целочисленным типом.
- И нужно использовать 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, в котором вы можете «построить» поток, который работает в этом порядке:
- сопоставляет число с полем map
- фильтровать их по полю фильтра
- создать коллекцию в качестве результата
Пример:
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. Спасибо за решение, но пока слишком сложно для меня)