Class NonEmptySet<T>

java.lang.Object
dmx.fun.NonEmptySet<T>
Type Parameters:
T - the type of elements in this set
All Implemented Interfaces:
Iterable<T>

@NullMarked public final class NonEmptySet<T> extends Object implements Iterable<T>
An immutable, non-empty set: a set guaranteed at construction time to contain at least one element.

This type makes the non-emptiness constraint part of the static type system. APIs that require at least one item can declare NonEmptySet<T> instead of Set<T> and eliminate runtime emptiness checks entirely.

Insertion order is preserved (backed by LinkedHashSet). The first element inserted is the head().

This class is @NullMarked: all elements and parameters are non-null by default.

The rationale for introducing dedicated non-empty collection types instead of using standard JDK types with runtime checks is documented in ADR-018 — NonEmptyList<T>, NonEmptySet<T>, NonEmptyMap<K,V> as structural guarantee types.

  • Method Details

    • of

      public static <T> NonEmptySet<T> of(T head, Set<? extends T> rest)
      Creates a NonEmptySet with the given head element and additional elements.

      If rest contains head, the duplicate is silently ignored.

      Type Parameters:
      T - the element type
      Parameters:
      head - the first (mandatory) element; must not be null
      rest - additional elements; must not be null; elements must not be null
      Returns:
      a new NonEmptySet
      Throws:
      NullPointerException - if head, rest, or any element in rest is null
    • singleton

      public static <T> NonEmptySet<T> singleton(T head)
      Creates a NonEmptySet containing exactly one element.
      Type Parameters:
      T - the element type
      Parameters:
      head - the sole element; must not be null
      Returns:
      a singleton NonEmptySet
      Throws:
      NullPointerException - if head is null
    • fromSet

      public static <T> Option<NonEmptySet<T>> fromSet(Set<? extends T> set)
      Attempts to construct a NonEmptySet from a plain Set.
      Type Parameters:
      T - the element type
      Parameters:
      set - the source set; must not be null; elements must not be null
      Returns:
      Option.some(Object) wrapping the NonEmptySet if the set is non-empty, or Option.none() if the set is empty
      Throws:
      NullPointerException - if set or any element is null
    • fromOptional

      public static <T> Option<NonEmptySet<T>> fromOptional(Optional<? extends T> optional)
      Attempts to construct a singleton NonEmptySet from a JDK Optional.
      Type Parameters:
      T - the element type
      Parameters:
      optional - the source optional; must not be null
      Returns:
      Option.some(Object) wrapping a singleton NonEmptySet if the optional is present, or Option.none() if the optional is empty
      Throws:
      NullPointerException - if optional is null
    • collector

      public static <T> Collector<T, ?, Option<NonEmptySet<T>>> collector()
      Returns a Collector that accumulates a Stream<T> into an Option<NonEmptySet<T>>.

      Produces Option.some(Object) for a non-empty stream and Option.none() for an empty stream. Duplicate elements are automatically deduplicated (set semantics).

      Example:

      Option<NonEmptySet<String>> roles =
          userRoles.stream()
              .collect(NonEmptySet.collector());
      
      Type Parameters:
      T - the element type
      Returns:
      a collector producing Option<NonEmptySet<T>>
    • head

      public T head()
      Returns the guaranteed head element of this set (the first inserted element).
      Returns:
      the head element (never null)
    • size

      public int size()
      Returns the number of elements in this set. Always ≥ 1.
      Returns:
      the size
    • contains

      public boolean contains(T element)
      Returns true if this set contains element.
      Parameters:
      element - the element to test; must not be null
      Returns:
      true if the element is present
      Throws:
      NullPointerException - if element is null
    • toSet

      public Set<T> toSet()
      Returns an unmodifiable Set containing all elements (head first, then tail in insertion order). The same instance is returned on repeated calls (lazily initialized, thread-safe).
      Returns:
      an unmodifiable set with all elements
    • toStream

      public Stream<T> toStream()
      Returns a sequential Stream of all elements in insertion order.

      The stream always contains at least one element (the head). Use it to bridge NonEmptySet into the standard Java stream API without going through toSet().

      Returns:
      a non-empty stream of elements in insertion order
    • map

      public <R> NonEmptySet<R> map(Function<? super T, ? extends R> mapper)
      Applies mapper to every element and returns a new NonEmptySet of the results. Duplicate mapped values are deduplicated; the head is always the mapped value of the original head.
      Type Parameters:
      R - the result element type
      Parameters:
      mapper - a non-null function to apply to each element; must not return null
      Returns:
      a new NonEmptySet of mapped values
      Throws:
      NullPointerException - if mapper is null or returns null
    • filter

      public Option<NonEmptySet<T>> filter(Predicate<? super T> predicate)
      Returns a new NonEmptySet containing elements that satisfy predicate, wrapped in Option.some(Object). Returns Option.none() if no elements pass the predicate.
      Parameters:
      predicate - a non-null predicate to test each element
      Returns:
      Some(filteredSet) if at least one element passes, None otherwise
      Throws:
      NullPointerException - if predicate is null
    • union

      public NonEmptySet<T> union(NonEmptySet<T> other)
      Returns a new NonEmptySet that is the union of this set and other. The result is always non-empty since both inputs are non-empty.
      Parameters:
      other - the other set; must not be null
      Returns:
      a new NonEmptySet containing all elements from both sets
      Throws:
      NullPointerException - if other is null
    • intersection

      public Option<NonEmptySet<T>> intersection(Set<? extends T> other)
      Returns a new NonEmptySet containing only elements present in both this set and other, wrapped in Option.some(Object). Returns Option.none() if the intersection is empty.
      Parameters:
      other - the set to intersect with; must not be null
      Returns:
      Some(intersection) if at least one common element exists, None otherwise
      Throws:
      NullPointerException - if other is null
    • toNonEmptyList

      public NonEmptyList<T> toNonEmptyList()
      Converts this set to a NonEmptyList of its elements in insertion order.
      Returns:
      a NonEmptyList<T> with the same elements
    • toNonEmptyMap

      public <V> NonEmptyMap<T,V> toNonEmptyMap(Function<? super T, ? extends V> valueMapper)
      Returns a NonEmptyMap by applying valueMapper to each element of this set. Elements become keys; mapped results become values. The head of this set is the head key of the returned map.
      Type Parameters:
      V - the value type
      Parameters:
      valueMapper - a non-null function to derive a value from each element; must not return null
      Returns:
      a new NonEmptyMap<T, V>
      Throws:
      NullPointerException - if valueMapper is null or returns null
    • sequenceOption

      public static <T> Option<NonEmptySet<T>> sequenceOption(NonEmptySet<Option<T>> nes)
      Sequences a NonEmptySet<Option<T>> into an Option<NonEmptySet<T>>.

      Returns Option.some(Object) containing all unwrapped values if every element is Some; returns Option.none() as soon as any element is None (fail-fast in inspection — the method stops iterating after the first None; elements are already materialized in the set before sequencing, so later elements are not inspected but were already evaluated).

      Type Parameters:
      T - the unwrapped element type
      Parameters:
      nes - a NonEmptySet<Option<T>>; must not be null
      Returns:
      Some(NonEmptySet<T>) if all elements are present, None otherwise
      Throws:
      NullPointerException - if nes is null
    • sequenceTry

      public static <T> Try<NonEmptySet<T>> sequenceTry(NonEmptySet<Try<T>> nes)
      Sequences a NonEmptySet<Try<T>> into a Try<NonEmptySet<T>>.

      Returns Try.success(Object) if all elements succeed; returns Try.failure(Throwable) from the first failing element (fail-fast in inspection — the method stops iterating after the first failure; elements are already materialized in the set before sequencing, so later elements are not inspected but were already evaluated).

      Type Parameters:
      T - the success value type
      Parameters:
      nes - a NonEmptySet<Try<T>>; must not be null
      Returns:
      Success(NonEmptySet<T>) if all succeed, Failure otherwise
      Throws:
      NullPointerException - if nes is null
    • sequenceEither

      public static <E,T> Either<E, NonEmptySet<T>> sequenceEither(NonEmptySet<Either<E,T>> nes)
      Sequences a NonEmptySet<Either<E, T>> into an Either<E, NonEmptySet<T>>.

      Returns Either.right(Object) if all elements are right; returns Either.left(Object) from the first left element (fail-fast in inspection — the method stops iterating after the first left; elements are already materialized in the set before sequencing, so later elements are not inspected but were already evaluated).

      Type Parameters:
      E - the left (error) type
      T - the right (success) type
      Parameters:
      nes - a NonEmptySet<Either<E, T>>; must not be null
      Returns:
      right(NonEmptySet<T>) if all are right, left(E) otherwise
      Throws:
      NullPointerException - if nes is null
    • sequenceResult

      public static <T,E> Result<NonEmptySet<T>, E> sequenceResult(NonEmptySet<Result<T,E>> nes)
      Sequences a NonEmptySet<Result<T, E>> into a Result<NonEmptySet<T>, E>.

      Returns Result.ok(Object) if all elements are ok; returns Result.err(Object) from the first error element (fail-fast in inspection — the method stops iterating after the first err; elements are already materialized in the set before sequencing, so later elements are not inspected but were already evaluated).

      Type Parameters:
      T - the ok value type
      E - the error type
      Parameters:
      nes - a NonEmptySet<Result<T, E>>; must not be null
      Returns:
      ok(NonEmptySet<T>) if all succeed, err(E) otherwise
      Throws:
      NullPointerException - if nes is null
    • iterator

      public Iterator<T> iterator()
      Returns an iterator over all elements (head first, then tail in insertion order).
      Specified by:
      iterator in interface Iterable<T>
      Returns:
      an iterator
    • equals

      public boolean equals(Object obj)
      Overrides:
      equals in class Object
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object
    • toString

      public String toString()
      Overrides:
      toString in class Object