My question contains 2 subquestions, therefore it is not limited to java but takes programming paradigms in general into consideration.
I need a Loop which does a usual "forEach" but also provides for each index its previous runs. Let me elaborate.
Let's define:
OBJECTS = a collection of X, where X is just any Type of Object/Data
PREV = the results of the previous iterations as a Collection of Y, Y beeing the result of a single iteration of an X
what "my" suplementalForEach would do is:
OBJECTS.supplementalForEach((PREV, OBJ) -> doStuff(PREV, OBJ))
or as non-stream variant
var PREV = new ArrayList<>();
for(var OBJ : OBJECTS) {
var result = doStuff(PREV, OBJ);
PREV.add(result);
}
So in essence in Java this would be a forEach, taking a BiFunction<R, T> instead of Consumer<T>
The Question now is, is there already a programming concept to this idea? If yes, what is it called? And if yes, is there a Java Implementation?
If no i can just implement it myself but this is a curious question of mine. Btw i didn't find anything yet on Google and Stackoverflow to this.
EDIT2: as of now i have implemented these methods, feel free to use them as you please (Keep the comments and references)
/**
* @author levent.dag
* https://stackoverflow.com/users/9648047/levent-dag
*
* naming idea with "akuzminykh"
* https://stackoverflow.com/users/12323248/akuzminykh , 02.06.2020
*
* <pre>
* Cumulative Iteration:
* the process of iterating with the results of the previous iterations
*
* definition:
* D domain (collection of X)
* X ∈ of domain, Data/Object/Value
* R results of previous iterations (List<Y>)
*
* f(R, X) iteration cycle/Function for current X element with the knowledge of previous iteration results R
*
*
* for X ∈ D {
* R.add(R, X)
* }
*
* ORDER sensible! use ordered Collections such as Lists and so on.
* </pre>
* @param <X>
* @param <Y>
* @param col
* @param loopIteration
*/
public static <X, Y, LIST extends List<Y>> void cumulativeIteration(final Collection<X> col, final BiFunction<List<Y>, X, Y> loopIteration, Class<Y> clazz) {
final ArrayList<Y> previous = new ArrayList<>();
col.forEach(x -> previous.add(loopIteration.apply(previous, x)));
}
/**
* @author levent.dag
* https://stackoverflow.com/users/9648047/levent-dag
*
* naming idea with "akuzminykh"
* https://stackoverflow.com/users/12323248/akuzminykh , 02.06.2020
*
* Same as {@link Essentials#additiveIteration(Collection, BiFunction)}, but the previous results can be mapped.
*
* @param <X>
* @param <Y>
* @param col
* @param loopIteration
* @param mapper
*/
public static <X, Y> void mappedCumulativeIteration(final Collection<X> col, final BiFunction<Map<String, Y>, X, Y> loopIteration, final Function<X, String> mapper) {
final Map<String, Y> previous = new LinkedHashMap<>();
col.forEach(x -> previous.put(mapper.apply(x), loopIteration.apply(previous, x)));
}
additionally as @daniu has pointed out you could achieve this with a collector, if you want to collect the given data.
col.stream().<List<Y>>collect(()->new ArrayList<>(), (pre, current) -> pre.add(loopIteration.apply(pre, current)), List::addAll);
Or as a standalone Collector
/**
* @author levent.dag
* https://stackoverflow.com/users/9648047/levent-dag
*
* naming idea with "akuzminykh"
* https://stackoverflow.com/users/12323248/akuzminykh , 02.06.2020
*
* <pre>
* Cumulative Iteration:
* the process of iterating with the results of the previous iterations
*
* definition:
* D domain (collection of X)
* X ∈ of domain, Data/Object/Value
* R results of previous iterations (List<Y>)
*
* f(R, X) iteration cycle/Function for current X element with the knowledge of previous iteration results R
*
*
* for X ∈ D {
* R.add(R, X)
* }
*
* ORDER sensible! use ordered Collections such as Lists and so on.
* </pre>
*
* @param <OBJECT>
* @param <RESULT>
*/
public class CumulativeListCollector<OBJECT, RESULT> implements Collector<OBJECT, List<RESULT>, List<RESULT>> {
private final BiFunction<List<RESULT>, OBJECT, RESULT> loopIteration;
public CumulativeListCollector(final BiFunction<List<RESULT>, OBJECT, RESULT> loopIteration) {
this.loopIteration = loopIteration;
}
public static <O,R> CumulativeListCollector<O, R> of(final BiFunction<List<R>, O, R> loopIteration) {
return new CumulativeListCollector<>(loopIteration);
}
@Override
public Supplier<List<RESULT>> supplier() {
return ()->new ArrayList<RESULT>();
}
@Override
public BiConsumer<List<RESULT>, OBJECT> accumulator() {
return (pre, current) -> pre.add(this.loopIteration.apply(pre, current));
}
@Override
public Function<List<RESULT>, List<RESULT>> finisher() {
return Function.identity();
}
@Override
public BinaryOperator<List<RESULT>> combiner() {
return (left, right)->{left.addAll(right); return left;};
}
@Override
public Set<Characteristics> characteristics() {
return Set.of();
}
}
>collect(()->new ArrayList<>(), (pre, current) -> pre.add(loopIteration.apply(pre, current)), List::addAll); I mean yeah, but in essence we are not trying to collect data but thanks for your contribution!
– Levent Dag Jun 02 '20 at 13:14