dev.marksman.collectionviews.Set 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.functions.Fn1;
import com.jnape.palatable.lambda.functions.builtin.fn2.Find;
import dev.marksman.enhancediterables.FiniteIterable;
import static com.jnape.palatable.lambda.adt.Maybe.just;
import static com.jnape.palatable.lambda.adt.Maybe.nothing;
import static dev.marksman.collectionviews.EmptySetBuilder.emptySetBuilder;
/**
* A finite, unordered view of a collection that contains no duplicate elements.
*
* A {@code Set} guarantees the following:
*
* - A {@link Set#size} method that executes in O(1).
*
- A {@link Set#contains} method that tests an value for membership in O(1).
*
- An {@link Set#isEmpty} method that executes in O(1).
*
- Iteration will always terminate.
*
- Protected from mutation by the bearer.
*
- The bearer cannot gain access to a reference to the underlying collection.
*
*
* @param the element type
*/
public interface Set extends FiniteIterable {
/**
* Tests if an element is a member of this {@code Set}.
*
* @param element the element to test
* @return true if {@code element} is a member of this {@link Set}, false otherwise
*/
boolean contains(A element);
/**
* Returns the size of this {@code Set}.
*
* Executes in O(1).
*
* @return the number of elements in this {@link Set}
*/
int size();
/**
* Since a {@code Set} already contains only distinct values, this method always
* returns itself.
*
* @return itself
*/
@Override
default Set distinct() {
return this;
}
/**
* Finds an element of this {@code Set} that satisfies a predicate, if any.
*
* @param predicate a predicate; not null
* @return an element wrapped in a {@link Maybe#just} if a matching element is found;
* {@link Maybe#nothing} otherwise.
*/
default Maybe find(Fn1 super A, ? extends Boolean> predicate) {
return Find.find(predicate, this);
}
/**
* Tests whether this {@link Set} is empty.
*
* Executes in O(1).
*
* @return true if this {@link Set} is empty, false otherwise.
*/
default boolean isEmpty() {
return size() == 0;
}
/**
* Converts this {@code Set} to an {@code ImmutableSet}.
* Converts this {@code Set} to an {@code ImmutableSet}.
*
* This method will make a copy of the underlying data structure if necessary to guarantee immutability.
*
* If this {@link Set} is already an {@link ImmutableSet}, no copies are made and this method is a no-op.
*
* @return an {@code ImmutableSet} of the same type and containing the same elements
*/
default ImmutableSet toImmutable() {
return ImmutableSets.ensureImmutable(this);
}
/**
* Attempts to convert this {@code Set} to a {@code NonEmptySet}.
*
* If successful, returns a {@link NonEmptySet} containing the same elements as this one, wrapped in a {@link Maybe#just}.
*
* If this {@code Set} is empty, returns {@link Maybe#nothing}.
*
* Does not make copies of any underlying data structures.
*
* @return a {@code Maybe>}
*/
default Maybe extends NonEmptySet> toNonEmpty() {
return Sets.maybeNonEmptyWrap(this);
}
/**
* Attempts to convert this {@code Set} to a {@code NonEmptySet}.
*
* If successful, returns a {@link NonEmptySet} containing the same elements as this one.
* Use this if you are confident that this {@link Set} is not empty.
*
* If this {@code Set} is empty, throws an {@link IllegalArgumentException}.
*
* Does not make copies of any underlying data structures.
*
* @return a {@code NonEmptySet}
* @throws IllegalArgumentException if this {@code Set} is empty
*/
default NonEmptySet toNonEmptyOrThrow() {
return Sets.nonEmptyWrapOrThrow(this);
}
/**
* Returns an empty {@link ImmutableSet}.
*
* @param the element type
* @return an empty {@code ImmutableSet}
*/
static ImmutableSet empty() {
return Sets.empty();
}
/**
* Creates a {@code ImmutableNonEmptySet} with the given elements.
*
* @param first the first element
* @param more the remaining elements
* @param the element type
* @return an {@code ImmutableNonEmptySet}
*/
@SuppressWarnings("varargs")
@SafeVarargs
static ImmutableNonEmptySet of(A first, A... more) {
return Sets.nonEmptySetOf(first, more);
}
/**
* Creates a new {@code SetBuilder}.
*
* @param the element type
* @return an empty {@link SetBuilder}
*/
static SetBuilder builder() {
return emptySetBuilder(nothing());
}
/**
* Creates a new {@code SetBuilder} with an initial capacity hint.
*
* @param initialCapacity an initial capacity hint.
* Must be >= 0.
* @param the element type
* @return an empty {@link SetBuilder}
*/
static SetBuilder builder(int initialCapacity) {
return emptySetBuilder(just(initialCapacity));
}
/**
* Creates a {@code Set} that wraps a {@code java.util.Set}.
*
* Does not make any copies of the given {@link java.util.Set}.
* The created {@link Set} will hold a reference to the given underlying {@code Set}, but will not alter it in any way.
*
* Bearers of the created {@code Set} will be unable to gain access to the underlying {@code Set}, so it is safe to share.
*
* Since no copy is made, be aware that anyone that holds a direct reference to the underlying {@code Set} can still mutate it.
* Mutating the underlying {@code Set} is not advised.
* Operations that change the size of the underlying {@code Set} will result in unpredictable behavior.
* Use {@link Set#copyFrom} if you want to avoid this situation.
*
* @param underlying {@code Set} to wrap; not null
* @param the element type
* @return a {@code Set}
*/
static Set wrap(java.util.Set underlying) {
return Sets.wrap(underlying);
}
/**
* Creates an {@code ImmutableSet} 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 ImmutableSet}, 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 ImmutableSet}
*/
static ImmutableSet copyFrom(Iterable source) {
return ImmutableSets.copyFrom(source);
}
/**
* Creates an {@code ImmutableSet} 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 ImmutableSet}
*/
static ImmutableSet copyFrom(A[] source) {
return ImmutableSets.copyFrom(source);
}
/**
* Creates an {@code ImmutableSet} that is copied from any {@code 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 ImmutableSet} and its size equal to {@code maxCount},
* in which case it will be returned directly.
*
* @param maxCount the maximum number of elements to consume from the source.
* Must be >= 0.
* @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 ImmutableSet} that contains at most {@code maxCount} elements
*/
static ImmutableSet copyFrom(int maxCount, Iterable source) {
return ImmutableSets.copyFrom(maxCount, source);
}
/**
* Returns a new {@code ImmutableSet} that is copied from an array.
*
* @param maxCount the maximum number of elements to copy from the array.
* Must be >= 0.
* @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 ImmutableSet}
*/
static ImmutableSet copyFrom(int maxCount, A[] source) {
return ImmutableSets.copyFrom(maxCount, source);
}
}