dev.marksman.collectionviews.ConcreteVectorBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of collection-views Show documentation
Show all versions of collection-views Show documentation
Low overhead, protected views over Java collections
package dev.marksman.collectionviews;
import com.jnape.palatable.lambda.adt.Maybe;
import dev.marksman.enhancediterables.FiniteIterable;
import dev.marksman.enhancediterables.NonEmptyFiniteIterable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
final class ConcreteVectorBuilder implements NonEmptyVectorBuilder {
private final Maybe initialCapacity;
private final ArrayList underlying;
private final int size;
private ConcreteVectorBuilder(int size, Maybe initialCapacity, ArrayList underlying) {
this.initialCapacity = initialCapacity;
this.underlying = underlying;
this.size = size;
}
@Override
public NonEmptyVectorBuilder add(A element) {
ArrayList nextUnderlying = getNextUnderlying();
nextUnderlying.add(element);
return concreteVectorBuilder(nextUnderlying.size(), initialCapacity, nextUnderlying);
}
@Override
public NonEmptyVectorBuilder addAll(Collection elements) {
Objects.requireNonNull(elements);
if (elements.isEmpty()) {
return this;
} else {
ArrayList nextUnderlying = getNextUnderlying();
nextUnderlying.addAll(elements);
return concreteVectorBuilder(nextUnderlying.size(), initialCapacity, nextUnderlying);
}
}
@Override
public NonEmptyVectorBuilder addAll(FiniteIterable elements) {
Objects.requireNonNull(elements);
if (elements.isEmpty()) {
return this;
} else {
return addAllImpl(elements);
}
}
@Override
public NonEmptyVectorBuilder addAll(NonEmptyFiniteIterable elements) {
return addAllImpl(elements);
}
@Override
public ImmutableNonEmptyVector build() {
return ImmutableVectors.wrapAndVouchFor(underlying).take(size).toNonEmptyOrThrow();
}
private NonEmptyVectorBuilder addAllImpl(Iterable elements) {
ArrayList nextUnderlying = getNextUnderlying();
for (A element : elements) {
nextUnderlying.add(element);
}
return concreteVectorBuilder(nextUnderlying.size(), initialCapacity, nextUnderlying);
}
private ArrayList getNextUnderlying() {
// If the size has changed, we need to make a copy
if (underlying.size() == size) {
return underlying;
} else {
ArrayList newUnderlying = initialCapacity.match(__ -> new ArrayList<>(), ArrayList::new);
for (int i = 0; i < size; i++) {
newUnderlying.add(underlying.get(i));
}
return newUnderlying;
}
}
static ConcreteVectorBuilder concreteVectorBuilder(int size, Maybe initialCapacity, ArrayList underlying) {
assert (size >= 1);
return new ConcreteVectorBuilder<>(size, initialCapacity, underlying);
}
static ConcreteVectorBuilder concreteVectorBuilder(Maybe initialCapacity, A firstElement) {
ArrayList underlying = initialCapacity.match(__ -> new ArrayList<>(), ArrayList::new);
underlying.add(firstElement);
return new ConcreteVectorBuilder<>(1, initialCapacity, underlying);
}
}