I have the following example data set that I want to transform / reduce using Java stream api based on direction\'s value
Direction int[]
IN 1, 2
O
How about this. First define a small helper method:
private static Tuple mergeTwo(Tuple left, Tuple right) {
int[] leftArray = left.getData();
int[] rightArray = right.getData();
int[] result = new int[leftArray.length + rightArray.length];
System.arraycopy(leftArray, 0, result, 0, leftArray.length);
System.arraycopy(rightArray, 0, result, leftArray.length, rightArray.length);
return new Tuple(left.getDirection(), result);
}
This is close to your concat/merge
I guess, but a single one. Basically a way to merge two Tuple
(s) together.
And a helper method to produce the needed Collector
, you can put this into a utility so that it can be re-used:
private static Collector> mergedTuplesCollector() {
class Acc {
ArrayDeque deque = new ArrayDeque<>();
void add(Tuple elem) {
Tuple head = deque.peek();
if (head == null || head.getDirection() != elem.getDirection()) {
deque.offerFirst(elem);
} else {
deque.offerFirst(mergeTwo(deque.poll(), elem));
}
}
Acc merge(Acc right) {
Tuple lastLeft = deque.peekLast();
Tuple firstRight = right.deque.peekFirst();
if (lastLeft.getDirection() == firstRight.getDirection()) {
deque.offerLast(mergeTwo(deque.pollLast(), right.deque.pollFirst()));
} else {
deque.addAll(right.deque);
}
return this;
}
public List finisher() {
return new ArrayList<>(deque);
}
}
return Collector.of(Acc::new, Acc::add, Acc::merge, Acc::finisher);
}
And usage would be, for example:
List merged = tuples.stream()
.parallel()
.collect(mergedTuplesCollector());