All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.marksman.collectionviews.NonEmptyVector Maven / Gradle / Ivy

There is a newer version: 1.2.3
Show newest version
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 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> 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); } }