dev.marksman.collectionviews.NonEmptyVector Maven / Gradle / Ivy
Show all versions of collection-views Show documentation
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 dev.marksman.enhancediterables.NonEmptyFiniteIterable;
import dev.marksman.enhancediterables.NonEmptyIterable;
import java.util.Iterator;
import java.util.List;
import static com.jnape.palatable.lambda.adt.Maybe.just;
import static com.jnape.palatable.lambda.adt.Maybe.nothing;
import static dev.marksman.collectionviews.ConcreteVectorBuilder.concreteVectorBuilder;
/**
* A {@code Vector} that is guaranteed at compile-time to contain at least one element.
*
* In addition to guarantees of {@link Vector}, provides the following benefits:
*
* - {@link NonEmptyVector#head} method that returns the first element.
* - Implements {@link NonEmptyIterable}.
* - {@link NonEmptyVector#fmap} always returns a {@code NonEmptyVector}.
* - {@link NonEmptyVector#reverse} always returns a {@code NonEmptyVector}.
* - {@link NonEmptyVector#zipWithIndex} always returns a {@code NonEmptyVector}.
*
*
* @param the element type
*/
public interface NonEmptyVector extends NonEmptyFiniteIterable, Vector {
/**
* Returns the cartesian product of this {@code NonEmptyVector} with another {@code NonEmptyVector}.
*
* Does not make copies of any underlying collections.
*
* The returned {@link NonEmptyVector} will have a size of {@code size()} × {@code other.size()},
* but will allocate no extra memory (aside from a few bytes for housekeeping).
*
* @param other a {@code NonEmptyVector} of any type
* @param the type of the other {@code NonEmptyVector}
* @return a {@code NonEmptyVector>}
*/
default NonEmptyVector> cross(NonEmptyVector other) {
return Vectors.nonEmptyCross(this, other);
}
/**
* Maps a function over this {@code NonEmptyVector}.
*
* Returns a new {@link NonEmptyVector} of the same size (but possibly a different type).
*
* Does not make any copies of underlying collections.
*
* This method is stack-safe, so a {@code NonEmptyVector} can be mapped as many times as the heap permits.
*
* @param f a function from {@code A} to {@code B}.
* Not null.
* This function should be referentially transparent and not perform side-effects.
* It may be called zero or more times for each element.
* @param The type of the elements contained in the output Vector.
* @return a {@code NonEmptyVector} of the same size
*/
@Override
default NonEmptyVector fmap(Fn1 super A, ? extends B> f) {
return Vectors.nonEmptyMap(f, this);
}
/**
* Returns the first element.
*
* @return an element of type {@code A}
*/
@Override
default A head() {
return unsafeGet(0);
}
/**
* Returns an {@code ImmutableNonEmptyVector} that contains all the indices of this {@code NonEmptyVector}.
*
* @return an {@code ImmutableNonEmptyVector}
*/
@Override
default ImmutableNonEmptyVector indices() {
return ImmutableVectors.nonEmptyIndices(this);
}
/**
* Returns the init of this {@code NonEmptyVector}.
*
* The init of a {@link NonEmptyVector} is the same {@code Vector} with the last element dropped.
* May be empty.
*
* Does not make copies of any underlying collections.
*
* @return a {@code Vector}
*/
default Vector init() {
return dropRight(1);
}
/**
* Tests whether this {@code NonEmptyVector} is empty.
*
* Always returns false for {@link NonEmptyVector}s.
*
* @return always false
*/
@Override
default boolean isEmpty() {
return false;
}
/**
* Returns an iterator over this {@code NonEmptyVector}'s elements.
*
* @return an Iterator.
*/
@Override
default Iterator iterator() {
return VectorHelpers.vectorIterator(this);
}
/**
* Returns the last element.
*
* @return an element of type {@code A}
*/
@Override
default A last() {
return unsafeGet(size() - 1);
}
/**
* Creates a {@code NonEmptyVector} with this {@code NonEmptyVector}'s elements in reversed order.
*
* Does not make copies of any underlying collections.
*
* @return a {@code NonEmptyVector}
*/
@Override
default NonEmptyVector reverse() {
return Vectors.nonEmptyReverse(this);
}
/**
* Returns the tail of this {@code NonEmptyVector}.
*
* The tail of a {@link NonEmptyVector} is the same {@code Vector} with the first element dropped.
* May be empty.
*
* Does not make copies of any underlying collections.
*
* @return a {@code Vector}
*/
@Override
default Vector tail() {
return drop(1);
}
/**
* Converts this {@code NonEmptyVector} to an {@code ImmutableNonEmptyVector}.
*
* This method will make a copy of the underlying data structure if necessary to guarantee immutability.
*
* If this {@link NonEmptyVector} is already an {@link ImmutableNonEmptyVector}, no copies are made and this method is a no-op.
*
* @return an {@code ImmutableNonEmptyVector} of the same type and containing the same elements
*/
@Override
default ImmutableNonEmptyVector toImmutable() {
return ImmutableVectors.ensureImmutable(this);
}
/**
* Attempts to convert this {@code Vector} to a {@code NonEmptyVector}.
*
* Since this will always be successful for {@link NonEmptyVector}s,
* this method always returns itself wrapped in a {@link Maybe#just}.
*
* Does not make copies of any underlying collections.
*
* @return this {@code NonEmptyVector} wrapped in a {@link Maybe#just}
*/
@Override
default Maybe extends NonEmptyVector> toNonEmpty() {
return just(this);
}
/**
* Attempts to convert this {@code Vector} to a {@code NonEmptyVector}.
*
* Since this will always be successful for {@link NonEmptyVector}s,
* this method always returns itself.
*
* Does not make copies of any underlying collections.
*
* @return this {@code NonEmptyVector}
*/
@Override
default NonEmptyVector toNonEmptyOrThrow() {
return this;
}
/**
* Zips together this {@code NonEmptyVector} with another {@code NonEmptyVector} by applying a zipping function.
*
* Applies the function to the successive elements of of each {@code NonEmptyVector} until one of them runs out of elements.
*
* Does not make copies of any underlying collections.
*
* @param fn The zipping function.
* Not null.
* This function should be referentially transparent and not perform side-effects.
* It may be called zero or more times for each element.
* @param other The other {@code NonEmptyVector}
* @param The element type of the other {@code NonEmptyVector}
* @param The element type of the result
* @return A {@code NonEmptyVector}
*/
default NonEmptyVector zipWith(Fn2 fn, NonEmptyVector other) {
return Vectors.nonEmptyZipWith(fn, this, other);
}
/**
* Zips this {@code NonEmptyVector} with its indices.
*
* Does not make copies of any underlying collections.
*
* @return a new {@code NonEmptyVector} containing pairs consisting of all elements of this {@code NonEmptyVector} paired with their index.
* Indices start at 0.
*/
@Override
default NonEmptyVector> zipWithIndex() {
return Vectors.nonEmptyZipWithIndex(this);
}
/**
* Creates a {@code ImmutableNonEmptyVector} with the given elements.
*
* @param first the first element
* @param more the remaining elements
* @param the element type
* @return an {@code ImmutableNonEmptyVector}
*/
@SuppressWarnings("varargs")
@SafeVarargs
static ImmutableNonEmptyVector of(A first, A... more) {
return Vectors.nonEmptyVectorOf(first, more);
}
/**
* Creates a new {@code NonEmptyVectorBuilder}.
*
* @param first the first element
* @param the element type
* @return an empty {@link VectorBuilder}
*/
static NonEmptyVectorBuilder builder(A first) {
return concreteVectorBuilder(nothing(), first);
}
/**
* Creates a new {@code NonEmptyVectorBuilder} with an initial capacity hint.
*
* @param initialCapacity an initial capacity hint.
* Must be >= 0.
* @param first the first element
* @param the element type
* @return an empty {@link VectorBuilder}
*/
static NonEmptyVectorBuilder builder(int initialCapacity, A first) {
return concreteVectorBuilder(just(initialCapacity), first);
}
/**
* Attempts to create a {@code NonEmptyVector} that wraps an array.
*
* Does not make any copies of the given array.
* The created {@link NonEmptyVector} will hold on to a reference to the array, but will never alter it in any way.
*
* Bearers of the created {@code NonEmptyVector} will be unable to gain access to the underlying array, it is safe to share.
*
* Since no copy is made, be aware that anyone that holds a direct reference to the array can still mutate it.
* Use {@link Vector#copyFrom} instead if you want to avoid this situation.
*
* @param underlying the array to wrap; not null
* @param the element type
* @return a {@code NonEmptyVector} wrapped in a {@link Maybe#just} if {@code underlying} is non-empty;
* {@link Maybe#nothing} otherwise.
*/
static Maybe> maybeWrap(A[] underlying) {
return Vectors.maybeNonEmptyWrap(underlying);
}
/**
* Attempts to create a {@code NonEmptyVector} that wraps a {@code java.util.List}.
*
* Does not make any copies of the given {@link java.util.List}.
* The created {@link NonEmptyVector} will hold a reference to the given {@link java.util.List}, but will not alter it in any way.
*
* Bearers of the {@code NonEmptyVector} will be unable to gain access to the underlying {@link java.util.List}, it is safe to share.
*
* Since no copy is made, be aware that anyone that holds a direct reference to the {@code List} can still mutate it.
* Mutating the {@code List} is not advised.
* Operations that change the size of the underlying {@code List} will result in unpredictable behavior.
* Use {@link Vector#copyFrom} if you want to avoid this situation.
*
* @param underlying {@code java.util.List} to wrap; not null
* @param the element type
* @return a {@code NonEmptyVector} wrapped in a {@link Maybe#just} if {@code underlying} is non-empty;
* {@link Maybe#nothing} otherwise.
*/
static Maybe> maybeWrap(List underlying) {
return Vectors.maybeNonEmptyWrap(underlying);
}
/**
* Attempts to create a {@code NonEmptyVector} that wraps an array.
* If it is not possible, throws an {@link IllegalArgumentException}.
*
* Does not make any copies of the given array.
* The created {@link NonEmptyVector} will hold on to a reference to the array, but will never alter it in any way.
*
* Bearers of the created {@code NonEmptyVector} will be unable to gain access to the underlying array, it is safe to share.
*
* Since no copy is made, be aware that anyone that holds a direct reference to the array can still mutate it.
* Use {@link NonEmptyVector#copyFromOrThrow(Object[])} instead if you want to avoid this situation.
*
* @param underlying array to wrap; not null
* @param the element type
* @return a {@code NonEmptyVector} if {@code underlying} is non-empty; throws an {@link IllegalArgumentException} otherwise
*/
static NonEmptyVector wrapOrThrow(A[] underlying) {
return Vectors.nonEmptyWrapOrThrow(underlying);
}
/**
* Attempts to create a {@code NonEmptyVector} that wraps a {@code java.util.List}.
* If it is not possible, throws an {@link IllegalArgumentException}.
*
* Does not make any copies of the given {@link java.util.List}.
* The created {@link NonEmptyVector} will hold a reference to the given {@code java.util.List}, but will not alter it in any way.
*
* Bearers of the created {@link NonEmptyVector} will be unable to gain access to the underlying {@code List}, it is safe to share.
*
* Since no copy is made, be aware that anyone that holds a direct reference to the {@code List} can still mutate it.
* Mutating the {@code List} is not advised.
* Operations that change the size of the underlying {@code List} will result in unpredictable behavior.
* Use {@link NonEmptyVector#copyFromOrThrow(Iterable)} if you want to avoid this situation.
*
* @param underlying {@code List} to wrap; not null
* @param the element type
* @return a {@code NonEmptyVector} if {@code underlying} is non-empty; throws an {@link IllegalArgumentException} otherwise
*/
static NonEmptyVector wrapOrThrow(List underlying) {
return Vectors.nonEmptyWrapOrThrow(underlying);
}
/**
* Attempts to create an {@code ImmutableNonEmptyVector} that is copied from any {@code Iterable}.
*
* The entire {@link Iterable} will be eagerly iterated.
* Be careful not to pass in an infinite {@code Iterable} or this method will not terminate.
*
* If necessary to guarantee immutability, this method will make a copy of the data provided.
* If {@code source} already is an {@link ImmutableNonEmptyVector}, it will be returned directly.
*
* @param source an {@code Iterable} that may be iterated eagerly in its entirety; not null
* @param the element type
* @return an {@code ImmutableNonEmptyVector} wrapped in a {@link Maybe#just} if {@code source} is non-empty;
* {@link Maybe#nothing} otherwise.
*/
static Maybe> maybeCopyFrom(Iterable source) {
return ImmutableVectors.maybeNonEmptyCopyFrom(source);
}
/**
* Attempts to create an {@code ImmutableNonEmptyVector} that is copied from an array.
*
* @param source the array to copy from.
* Not null.
* This method will not alter or hold on to a reference of this array.
* @param the element type
* @return an {@code ImmutableNonEmptyVector} wrapped in a {@link Maybe#just} if {@code source} is non-empty;
* {@link Maybe#nothing} otherwise.
*/
static Maybe> maybeCopyFrom(A[] source) {
return ImmutableVectors.maybeNonEmptyCopyFrom(source);
}
/**
* Attempts to create an {@code ImmutableNonEmptyVector} that is copied from any {@link Iterable}, but consuming a maximum number of elements.
*
* The {@link Iterable} will be eagerly iterated, but only up to a maximum of {@code maxCount} elements.
* If {@code maxCount} elements are not available, then the all of the elements available will be returned.
*
* This method will make a copy of the data provided, unless {@code source} is
* an {@link ImmutableVector} and its size is less than or equal to {@code maxCount},
* in which case it will be returned directly.
*
* If {@code source} is an {@code ImmutableVector} that is greater than {@code maxCount} in size,
* a copy will always be made, therefore making it memory-safe to take a small slice of
* a huge {@link Vector} that you no longer need.
*
* @param maxCount the maximum number of elements to consume from the source.
* Must be >= 0.
* If 0, this method will always return {@link Maybe#nothing}.
* @param source an {@code Iterable} that will be iterated eagerly for up to {@code maxCount} elements.
* Not null.
* It is safe for {@code source} to be infinite.
* @param the element type
* @return an {@code ImmutableNonEmptyVector} wrapped in a {@link Maybe#just} if {@code source} is non-empty;
* {@link Maybe#nothing} otherwise.
*/
static Maybe> maybeCopyFrom(int maxCount, Iterable source) {
return ImmutableVectors.maybeNonEmptyCopyFrom(maxCount, source);
}
/**
* Attempts to create an {@code ImmutableNonEmptyVector} that is copied from an array, but with a maximum number of elements.
*
* @param maxCount the maximum number of elements to copy from the array.
* Must be >= 0.
* If 0, this method will always return {@link Maybe#nothing}.
* @param source the array to copy from.
* Not null.
* This method will not alter or hold on to a reference of this array.
* @param the element type
* @return an {@code ImmutableNonEmptyVector} wrapped in a {@link Maybe#just} if {@code source} is non-empty;
* {@link Maybe#nothing} otherwise.
*/
static Maybe> maybeCopyFrom(int maxCount, A[] source) {
return ImmutableVectors.maybeNonEmptyCopyFrom(maxCount, source);
}
/**
* Attempts to create an {@code ImmutableNonEmptyVector} from any {@code Iterable}.
* If the {@link Iterable} is empty, throws an {@link IllegalArgumentException}.
*
* The entire {@link Iterable} will be eagerly iterated.
* Be careful not to pass in an infinite {@code Iterable} or this method will not terminate.
*
* If necessary to guarantee immutability, this method will make a copy of the data provided.
* If {@code source} already is an {@link ImmutableVector}, it will be returned directly.
*
* @param source an {@code Iterable} that will be iterated eagerly in its entirety; not null
* @param the element type
* @return an {@code ImmutableNonEmptyVector}
*/
static ImmutableNonEmptyVector copyFromOrThrow(Iterable source) {
return ImmutableVectors.nonEmptyCopyFromOrThrow(source);
}
/**
* Attempts to create an {@code ImmutableNonEmptyVector} that is copied from an array.
* If the array is empty, throws an {@link IllegalArgumentException}.
*
* @param source the array to copy from.
* Not null.
* This method will not alter or hold on to a reference of this array.
* @param the element type
* @return an {@code ImmutableNonEmptyVector}
*/
static ImmutableNonEmptyVector copyFromOrThrow(A[] source) {
return ImmutableVectors.nonEmptyCopyFromOrThrow(source);
}
/**
* Attempts to create an {@code ImmutableNonEmptyVector} from any {@code Iterable}, but consuming a maximum number of elements.
* If the {@link Iterable} is empty, throws an {@link IllegalArgumentException}.
*
* The {@code Iterable} will be eagerly iterated, but only up to a maximum of {@code maxCount} elements.
* If {@code maxCount} elements are not available, then the all of the elements available will be returned.
*
* This method will make a copy of the data provided, unless {@code source} is
* an {@link ImmutableVector} and its size is less than or equal to {@code maxCount},
* in which case it will be returned directly.
*
* If {@code source} is an {@code ImmutableVector} that is greater than {@code maxCount} in size,
* a copy will always be made, therefore making it memory-safe to take a small slice of
* a huge {@link Vector} that you no longer need.
*
* @param maxCount the maximum number of elements to consume from the source. Must be >= 1.
* @param source an {@code Iterable} that will be iterated eagerly for up to {@code maxCount} elements.
* Not null.
* It is safe for {@code source} to be infinite.
* @param the element type
* @return an {@code ImmutableNonEmptyVector}
*/
static ImmutableNonEmptyVector copyFromOrThrow(int maxCount, Iterable source) {
return ImmutableVectors.nonEmptyCopyFromOrThrow(maxCount, source);
}
/**
* Attempts to create an {@code ImmutableNonEmptyVector} that is copied from an array, but with a maximum number of elements.
* If the array is empty, throws an {@link IllegalArgumentException}.
*
* @param maxCount the maximum number of elements to copy from the array.
* Must be >= 1.
* @param source the array to copy from.
* Not null.
* This method will not alter or hold on to a reference of this array.
* @param the element type
* @return an {@code ImmutableNonEmptyVector}
*/
static ImmutableNonEmptyVector copyFromOrThrow(int maxCount, A[] source) {
return ImmutableVectors.nonEmptyCopyFromOrThrow(maxCount, source);
}
/**
* Creates an {@code ImmutableNonEmptyVector} that repeats the same element {@code size} times.
*
* Uses O(1) memory.
*
* @param size the number of elements.
* Must be >= 1.
* @param value the value that will be repeated all elements of the {@link ImmutableNonEmptyVector}
* @param the element type
* @return an {@code ImmutableVector} of {@code size} elements, with each element having
* the value {@code value}
*/
static ImmutableNonEmptyVector fill(int size, A value) {
return ImmutableVectors.nonEmptyFill(size, value);
}
/**
* Creates an {@code ImmutableNonEmptyVector} where elements are lazily evaluated.
*
* Uses O(1) memory.
*
* @param size the number of elements.
* Must be >= 1.
* @param valueSupplier a function that accepts an index and returns the computed value for
* that index. This function should be referentially transparent and not
* perform side-effects. It may be called zero or more times for each element.
* @param the element type
* @return an {@code ImmutableNonEmptyVector}
*/
static ImmutableNonEmptyVector lazyFill(int size, Fn1 valueSupplier) {
return ImmutableVectors.nonEmptyLazyFill(size, valueSupplier);
}
/**
* Creates an {@code ImmutableNonEmptyVector} that is copied from any {@code NonEmptyIterable}.
*
* The entire {@link NonEmptyIterable} will be eagerly iterated.
* Be careful not to pass in an infinite {@code NonEmptyIterable} or this method will not terminate.
*
* If necessary to guarantee immutability, this method will make a copy of the data provided.
* If {@code source} is an untransformed {@link ImmutableNonEmptyVector}, it will be returned directly.
*
* @param source a {@code NonEmptyIterable} that will be iterated eagerly in its entirety; not null
* @param the element type
* @return an {@code ImmutableNonEmptyVector}
*/
static ImmutableNonEmptyVector nonEmptyCopyFrom(NonEmptyIterable source) {
return ImmutableVectors.nonEmptyCopyFrom(source);
}
/**
* Creates an {@code ImmutableNonEmptyVector} that is copied from any {@code NonEmptyIterable}, but consuming a maximum number of elements.
*
* The {@link NonEmptyIterable} will be eagerly iterated, but only up to a maximum of {@code maxCount} elements.
* If {@code maxCount} elements are not available, then the all of the elements available will be returned.
*
* This method will make a copy of the data provided, unless {@code source} is
* an untransformed {@link ImmutableNonEmptyVector} and its size is less than or equal to {@code maxCount},
* in which case it will be returned directly.
*
* If {@code source} is an {@code ImmutableNonEmptyVector} that is greater than {@code maxCount} in size,
* a copy will always be made, therefore making it memory-safe to take a small slice of
* a huge {@link Vector} that you no longer need.
*
* @param maxCount the maximum number of elements to consume from the source.
* Must be >= 1.
* @param source a {@code NonEmptyIterable} that will be iterated eagerly for up to {@code maxCount} elements.
* Not null.
* It is safe for {@code source} to be infinite.
* @param the element type
* @return an {@code ImmutableNonEmptyVector} that contains at most {@code maxCount} elements
*/
static ImmutableNonEmptyVector nonEmptyCopyFrom(int maxCount, NonEmptyIterable source) {
return ImmutableVectors.nonEmptyCopyFrom(maxCount, source);
}
/**
* Creates an {@code ImmutableNonEmptyVector} containing elements 0..size - 1
.
* In other words, each element of the returned {@code Vector} will contains its index.
*
* Uses O(1) memory.
*
* @param size the number of elements.
* Must be >= 1.
* @return an {@code ImmutableNonEmptyVector}
*/
static ImmutableNonEmptyVector range(int size) {
return ImmutableVectors.nonEmptyRange(size);
}
}