| 1 | package com.pivovarit.gatherers; | |
| 2 | ||
| 3 | import java.util.concurrent.atomic.AtomicInteger; | |
| 4 | import java.util.function.BiConsumer; | |
| 5 | import java.util.function.Consumer; | |
| 6 | import java.util.function.Supplier; | |
| 7 | import java.util.stream.Gatherer; | |
| 8 | ||
| 9 | final class LastGatherer { | |
| 10 | private LastGatherer() { | |
| 11 | } | |
| 12 | ||
| 13 | static <T> Gatherer<T, ?, T> size(int n) { | |
| 14 |
1
1. size : replaced return value with null for com/pivovarit/gatherers/LastGatherer::size → KILLED |
return switch (n) { |
| 15 | case 1 -> new SingleElementLastGatherer<>(); | |
| 16 | default -> new CircularBufferLastGatherer<>(n); | |
| 17 | }; | |
| 18 | } | |
| 19 | ||
| 20 | private record CircularBufferLastGatherer<T>( | |
| 21 | long n) implements Gatherer<T, CircularBufferLastGatherer.AppendOnlyCircularBuffer<T>, T> { | |
| 22 | ||
| 23 | CircularBufferLastGatherer { | |
| 24 | if (n <= 0) { | |
| 25 | throw new IllegalArgumentException("number of elements can't be lower than one"); | |
| 26 | } | |
| 27 | } | |
| 28 | ||
| 29 | @Override | |
| 30 | public Supplier<AppendOnlyCircularBuffer<T>> initializer() { | |
| 31 |
2
1. lambda$initializer$0 : replaced return value with null for com/pivovarit/gatherers/LastGatherer$CircularBufferLastGatherer::lambda$initializer$0 → KILLED 2. initializer : replaced return value with null for com/pivovarit/gatherers/LastGatherer$CircularBufferLastGatherer::initializer → KILLED |
return () -> new AppendOnlyCircularBuffer<>((int) n); |
| 32 | } | |
| 33 | ||
| 34 | @Override | |
| 35 | public Integrator<AppendOnlyCircularBuffer<T>, T, T> integrator() { | |
| 36 |
1
1. integrator : replaced return value with null for com/pivovarit/gatherers/LastGatherer$CircularBufferLastGatherer::integrator → KILLED |
return Integrator.ofGreedy((state, element, _) -> { |
| 37 |
1
1. lambda$integrator$0 : removed call to com/pivovarit/gatherers/LastGatherer$CircularBufferLastGatherer$AppendOnlyCircularBuffer::add → KILLED |
state.add(element); |
| 38 |
1
1. lambda$integrator$0 : replaced boolean return with false for com/pivovarit/gatherers/LastGatherer$CircularBufferLastGatherer::lambda$integrator$0 → SURVIVED |
return true; |
| 39 | }); | |
| 40 | } | |
| 41 | ||
| 42 | @Override | |
| 43 | public BiConsumer<AppendOnlyCircularBuffer<T>, Downstream<? super T>> finisher() { | |
| 44 |
1
1. finisher : replaced return value with null for com/pivovarit/gatherers/LastGatherer$CircularBufferLastGatherer::finisher → KILLED |
return (state, downstream) -> { |
| 45 |
1
1. lambda$finisher$0 : negated conditional → KILLED |
if (!downstream.isRejecting()) { |
| 46 |
1
1. lambda$finisher$0 : removed call to com/pivovarit/gatherers/LastGatherer$CircularBufferLastGatherer$AppendOnlyCircularBuffer::forEach → KILLED |
state.forEach(downstream::push); |
| 47 | } | |
| 48 | }; | |
| 49 | } | |
| 50 | ||
| 51 | static class AppendOnlyCircularBuffer<T> { | |
| 52 | private final T[] buffer; | |
| 53 | private final int maxSize; | |
| 54 | private final AtomicInteger endIdx = new AtomicInteger(0); | |
| 55 | private final AtomicInteger size = new AtomicInteger(0); | |
| 56 | ||
| 57 | public AppendOnlyCircularBuffer(int size) { | |
| 58 | this.maxSize = size; | |
| 59 | this.buffer = (T[]) new Object[size]; | |
| 60 | } | |
| 61 | ||
| 62 | public void add(T element) { | |
| 63 |
1
1. add : Replaced integer modulus with multiplication → KILLED |
buffer[endIdx.getAndIncrement() % maxSize] = element; |
| 64 |
2
1. add : changed conditional boundary → KILLED 2. add : negated conditional → KILLED |
if (size.get() < maxSize) { |
| 65 | size.incrementAndGet(); | |
| 66 | } | |
| 67 | } | |
| 68 | ||
| 69 | public void forEach(Consumer<T> consumer) { | |
| 70 |
3
1. forEach : Replaced integer addition with subtraction → KILLED 2. forEach : Replaced integer modulus with multiplication → KILLED 3. forEach : Replaced integer subtraction with addition → KILLED |
int startIdx = (endIdx.get() - size.get() + maxSize) % maxSize; |
| 71 |
2
1. forEach : negated conditional → TIMED_OUT 2. forEach : changed conditional boundary → KILLED |
for (int i = 0; i < size.get(); i++) { |
| 72 |
3
1. forEach : Replaced integer modulus with multiplication → KILLED 2. forEach : Replaced integer addition with subtraction → KILLED 3. forEach : removed call to java/util/function/Consumer::accept → KILLED |
consumer.accept(buffer[(startIdx + i) % maxSize]); |
| 73 | } | |
| 74 | } | |
| 75 | } | |
| 76 | } | |
| 77 | ||
| 78 | private record SingleElementLastGatherer<T>() implements Gatherer<T, SingleElementLastGatherer.ValueHolder<T>, T> { | |
| 79 | ||
| 80 | @Override | |
| 81 | public Supplier<ValueHolder<T>> initializer() { | |
| 82 |
1
1. initializer : replaced return value with null for com/pivovarit/gatherers/LastGatherer$SingleElementLastGatherer::initializer → KILLED |
return ValueHolder::new; |
| 83 | } | |
| 84 | ||
| 85 | @Override | |
| 86 | public Integrator<ValueHolder<T>, T, T> integrator() { | |
| 87 |
1
1. integrator : replaced return value with null for com/pivovarit/gatherers/LastGatherer$SingleElementLastGatherer::integrator → KILLED |
return Integrator.ofGreedy((state, element, _) -> { |
| 88 | state.value = element; | |
| 89 | state.isSet = true; | |
| 90 |
1
1. lambda$integrator$0 : replaced boolean return with false for com/pivovarit/gatherers/LastGatherer$SingleElementLastGatherer::lambda$integrator$0 → SURVIVED |
return true; |
| 91 | }); | |
| 92 | } | |
| 93 | ||
| 94 | @Override | |
| 95 | public BiConsumer<ValueHolder<T>, Downstream<? super T>> finisher() { | |
| 96 |
1
1. finisher : replaced return value with null for com/pivovarit/gatherers/LastGatherer$SingleElementLastGatherer::finisher → KILLED |
return (state, downstream) -> { |
| 97 |
2
1. lambda$finisher$0 : negated conditional → KILLED 2. lambda$finisher$0 : negated conditional → KILLED |
if (state.isSet && !downstream.isRejecting()) { |
| 98 | downstream.push(state.value); | |
| 99 | } | |
| 100 | }; | |
| 101 | } | |
| 102 | ||
| 103 | static class ValueHolder<T> { | |
| 104 | private T value; | |
| 105 | private boolean isSet; | |
| 106 | } | |
| 107 | } | |
| 108 | } | |
Mutations | ||
| 14 |
1.1 |
|
| 31 |
1.1 2.2 |
|
| 36 |
1.1 |
|
| 37 |
1.1 |
|
| 38 |
1.1 |
|
| 44 |
1.1 |
|
| 45 |
1.1 |
|
| 46 |
1.1 |
|
| 63 |
1.1 |
|
| 64 |
1.1 2.2 |
|
| 70 |
1.1 2.2 3.3 |
|
| 71 |
1.1 2.2 |
|
| 72 |
1.1 2.2 3.3 |
|
| 82 |
1.1 |
|
| 87 |
1.1 |
|
| 90 |
1.1 |
|
| 96 |
1.1 |
|
| 97 |
1.1 2.2 |