dev.marksman.collectionviews.ImmutableVectors 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 com.jnape.palatable.lambda.adt.hlist.Tuple2;
import com.jnape.palatable.lambda.functions.Fn1;
import com.jnape.palatable.lambda.functions.Fn2;
import com.jnape.palatable.lambda.functions.builtin.fn2.Take;
import dev.marksman.enhancediterables.ImmutableNonEmptyFiniteIterable;
import dev.marksman.enhancediterables.NonEmptyIterable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import static com.jnape.palatable.lambda.adt.Maybe.just;
import static com.jnape.palatable.lambda.adt.Maybe.nothing;
import static com.jnape.palatable.lambda.adt.hlist.HList.tuple;
import static com.jnape.palatable.lambda.functions.builtin.fn1.Id.id;
import static com.jnape.palatable.lambda.functions.builtin.fn2.Into.into;
import static com.jnape.palatable.lambda.functions.builtin.fn2.ToCollection.toCollection;
import static com.jnape.palatable.lambda.functions.builtin.fn2.Tupler2.tupler;
import static dev.marksman.collectionviews.ImmutableCrossJoinVector.immutableCrossJoinVector;
import static dev.marksman.collectionviews.ImmutableReverseVector.immutableReverseVector;
import static dev.marksman.collectionviews.ImmutableVectorZip.immutableVectorZip;
import static dev.marksman.collectionviews.MapperChain.mapperChain;
import static dev.marksman.collectionviews.Validation.*;
import static dev.marksman.collectionviews.Vector.empty;
import static dev.marksman.collectionviews.VectorSlicing.sliceImpl;
final class ImmutableVectors {
private ImmutableVectors() {
}
static ImmutableVector copyFrom(A[] source) {
Objects.requireNonNull(source);
return copyFrom(source.length, source);
}
static ImmutableVector copyFrom(int maxCount, A[] source) {
validateCopyFrom(maxCount, source);
int count = Math.min(maxCount, source.length);
A[] copied = Arrays.copyOf(source, count);
return wrapAndVouchFor(copied);
}
static ImmutableVector copyFrom(Iterable source) {
Objects.requireNonNull(source);
if (source instanceof ImmutableVector> && Util.isPrimitive(source)) {
return (ImmutableVector) source;
} else if (!source.iterator().hasNext()) {
return Vectors.empty();
} else {
ArrayList copied = toCollection(ArrayList::new, source);
return wrapAndVouchFor(copied);
}
}
static ImmutableVector copyFrom(int maxCount, Iterable source) {
validateCopyFrom(maxCount, source);
if (maxCount == 0) {
return Vectors.empty();
}
if (source instanceof ImmutableVector> && Util.isPrimitive(source)) {
return ((ImmutableVector) source).take(maxCount);
} else {
return copyFrom(Take.take(maxCount, source));
}
}
static ImmutableVector copySliceFrom(int startIndex, int endIndexExclusive, Iterable source) {
validateSlice(startIndex, endIndexExclusive, source);
if (source instanceof ImmutableVector> && Util.isPrimitive(source)) {
return ((ImmutableVector) source).slice(startIndex, endIndexExclusive);
} else {
return Vectors.sliceFromIterable(startIndex, endIndexExclusive, source).toImmutable();
}
}
static ImmutableVector> cross(ImmutableVector first, ImmutableVector second) {
return second.toNonEmpty()., ImmutableNonEmptyVector>>zip(first.toNonEmpty()
.fmap(tupler()))
.match(__ -> empty(),
into(ImmutableVectors::nonEmptyCross));
}
static ImmutableVector drop(int count, ImmutableVector source) {
return VectorSlicing.dropImpl(ImmutableVectorSlice::immutableVectorSlice, count, source);
}
static ImmutableVector dropRight(int count, ImmutableVector source) {
validateDrop(count, source);
int size = source.size();
if (count >= size) {
return empty();
} else {
return take(size - count, source);
}
}
static ImmutableVector dropWhile(Fn1 super A, ? extends Boolean> predicate, ImmutableVector source) {
Objects.requireNonNull(predicate);
Objects.requireNonNull(source);
return drop(Vectors.findPrefixLength(predicate, source), source);
}
static ImmutableVector ensureImmutable(Vector vector) {
if (vector instanceof ImmutableVector>) {
return (ImmutableVector) vector;
} else if (vector.isEmpty()) {
return Vectors.empty();
} else {
ArrayList copied = toCollection(ArrayList::new, vector);
return wrapAndVouchFor(copied);
}
}
static ImmutableNonEmptyVector ensureImmutable(NonEmptyVector vector) {
if (vector instanceof ImmutableNonEmptyVector>) {
return (ImmutableNonEmptyVector) vector;
} else {
ArrayList copied = toCollection(ArrayList::new, vector);
return new ImmutableListVector<>(copied);
}
}
static ImmutableVector fill(int size, A value) {
validateFill(size);
if (size == 0) {
return Vectors.empty();
} else {
return nonEmptyFill(size, value);
}
}
static ImmutableVector indices(Vector vec) {
return range(vec.size());
}
static ImmutableNonEmptyFiniteIterable> inits(ImmutableVector source) {
return nonEmptyRange(source.size() + 1).fmap(source::dropRight);
}
static ImmutableVector lazyFill(int size, Fn1 valueSupplier) {
validateFill(size);
Objects.requireNonNull(valueSupplier);
if (size == 0) {
return Vectors.empty();
} else {
return nonEmptyLazyFill(size, valueSupplier);
}
}
static ImmutableVector extends ImmutableNonEmptyVector> magnetizeBy(Fn2 predicate, ImmutableVector source) {
Objects.requireNonNull(predicate);
return source.toNonEmpty().match(__ -> Vectors.empty(),
ne -> nonEmptyMagnetizeBy(predicate, ne));
}
static ImmutableVector map(Fn1 super A, ? extends B> f, ImmutableVector source) {
return maybeNonEmptyConvert(source)
.match(__ -> Vectors.empty(),
nonEmpty -> nonEmptyMap(f, nonEmpty));
}
static Maybe> maybeNonEmptyConvert(ImmutableVector vec) {
Objects.requireNonNull(vec);
if (vec instanceof ImmutableNonEmptyVector>) {
return just((ImmutableNonEmptyVector) vec);
} else if (!vec.isEmpty()) {
return just(new ImmutableVectorCons<>(vec.unsafeGet(0), vec.drop(1)));
} else {
return nothing();
}
}
@SuppressWarnings("unchecked")
static Maybe> maybeNonEmptyCopyFrom(A[] arr) {
Objects.requireNonNull(arr);
if (arr.length == 0) {
return nothing();
} else {
return (Maybe>) copyFrom(arr).toNonEmpty();
}
}
@SuppressWarnings("unchecked")
static Maybe> maybeNonEmptyCopyFrom(int maxCount, A[] arr) {
validateCopyFrom(maxCount, arr);
if (arr.length == 0 || maxCount == 0) {
return nothing();
} else {
return (Maybe>) copyFrom(maxCount, arr).toNonEmpty();
}
}
@SuppressWarnings("unchecked")
static Maybe> maybeNonEmptyCopyFrom(Iterable source) {
Objects.requireNonNull(source);
if (!source.iterator().hasNext()) {
return nothing();
}
return (Maybe>) copyFrom(source).toNonEmpty();
}
@SuppressWarnings("unchecked")
static Maybe> maybeNonEmptyCopyFrom(int maxCount, Iterable source) {
validateCopyFrom(maxCount, source);
if (maxCount == 0) {
return nothing();
}
if (!source.iterator().hasNext()) {
return nothing();
}
return (Maybe>) copyFrom(maxCount, source).toNonEmpty();
}
static ImmutableNonEmptyVector nonEmptyConvertOrThrow(ImmutableVector source) {
return getNonEmptyOrThrow(maybeNonEmptyConvert(source));
}
static ImmutableNonEmptyVector nonEmptyCopyFrom(NonEmptyIterable source) {
Objects.requireNonNull(source);
return coerceNonEmpty(copyFrom(source));
}
static ImmutableNonEmptyVector nonEmptyCopyFrom(int maxCount, NonEmptyIterable source) {
Validation.validateNonEmptyCopyFrom(maxCount, source);
return coerceNonEmpty(copyFrom(source.take(maxCount)));
}
static ImmutableNonEmptyVector nonEmptyCopyFromOrThrow(Iterable source) {
return getNonEmptyOrThrow(maybeNonEmptyCopyFrom(source));
}
static ImmutableNonEmptyVector nonEmptyCopyFromOrThrow(int maxCount, Iterable source) {
return getNonEmptyOrThrow(maybeNonEmptyCopyFrom(maxCount, source));
}
static ImmutableNonEmptyVector nonEmptyCopyFromOrThrow(A[] source) {
return getNonEmptyOrThrow(maybeNonEmptyCopyFrom(source));
}
static ImmutableNonEmptyVector nonEmptyCopyFromOrThrow(int maxCount, A[] source) {
return getNonEmptyOrThrow(maybeNonEmptyCopyFrom(maxCount, source));
}
static ImmutableNonEmptyVector> nonEmptyCross(ImmutableNonEmptyVector first, ImmutableNonEmptyVector second) {
return immutableCrossJoinVector(first, second);
}
static ImmutableNonEmptyVector nonEmptyFill(int size, A value) {
validateNonEmptyFill(size);
return new RepeatingVector<>(size, value);
}
static ImmutableNonEmptyVector nonEmptyIndices(NonEmptyVector vec) {
return nonEmptyRange(vec.size());
}
static ImmutableNonEmptyVector nonEmptyLazyFill(int size, Fn1 valueSupplier) {
validateNonEmptyFill(size);
return new LazyVector<>(size, 0, valueSupplier);
}
static ImmutableNonEmptyVector extends ImmutableNonEmptyVector> nonEmptyMagnetizeBy(Fn2 predicate, ImmutableNonEmptyVector source) {
Objects.requireNonNull(predicate);
int size = source.size();
VectorBuilder> builder = Vector.builder();
int index = 0;
while (index < size) {
Tuple2, Integer> next = magnetizeAt(predicate, index, source);
builder = builder.add(next._1());
index = next._2();
}
return builder.build().toNonEmptyOrThrow();
}
@SuppressWarnings("unchecked")
static ImmutableNonEmptyVector nonEmptyMap(Fn1 super A, ? extends B> f, ImmutableNonEmptyVector source) {
return new ImmutableMappedVector<>(mapperChain((Fn1