e.g.#1
[1, 1, 1, 2, 22, 35, 35, 120, 320]
==>> [3, 2, 22, 70, 120, 320]
note how repeated consecutive 1\'s and 35\'s are coalesced to 3 and 70
Stream.of(1, 1, 1, 2, 22, 35, 35, 120, 320)
.collect(Collectors.toMap(
Function.identity(),
Function.identity(),
Integer::sum,
LinkedHashMap::new
))
.values()
.forEach(System.out::println);
In the case the you posted a comment, you would need a custom collector, actually:
static class Custom implements Collector<Integer, List<Integer>, List<Integer>> {
private Integer match;
@Override
public Supplier<List<Integer>> supplier() {
return ArrayList::new;
}
@Override
public BiConsumer<List<Integer>, Integer> accumulator() {
return (list, x) -> {
int lastIndex = list.size() - 1;
if (match != null && match.equals(x)) {
list.set(lastIndex, list.get(lastIndex) + x);
} else {
match = x;
list.add(x);
}
};
}
@Override
public BinaryOperator<List<Integer>> combiner() {
return (left, right) -> {
throw new RuntimeException("Not for parallel");
};
}
@Override
public Function<List<Integer>, List<Integer>> finisher() {
return Function.identity();
}
@Override
public Set<Characteristics> characteristics() {
return Set.of();
}
}
And usage would be:
public static void main(String[] args) {
Stream.of(1, 1, 3, 1, 1)
.collect(new Custom())
.forEach(System.out::println);
}
Here is an approach using a stack.
public static List<Integer> coalesce(List<Integer> list) {
Stack<Integer> stack = new Stack<>();
stack.addAll(list);
List<Integer> sums = new ArrayList<>();
int sum = 0;
while (!stack.isEmpty()) {
int val = stack.pop();
sum += val;
if (!stack.isEmpty() && stack.peek() != val) {
sums.add(0,sum);
sum = 0;
}
}
sums.add(0,sum);
return sums;
}
Why bother using streams when you can do it with a simple for loop and an if-else block?
List<Integer> list = List.of(0, 0, 0, 0, 1, 1, 1, 0, 0, 0);
List<Integer> result = new ArrayList<>();
Integer curr = list.get(0);
Integer sum = 0;
for(Integer i : list){
if(i.equals(curr)){
sum += i;
}
else{
result.add(sum);
sum = i;
curr = i;
}
}
result.add(sum);
System.out.println(result);