Set
Set<E> is an ordered collection of unique elements. Duplicate values are silently ignored on insertion. Sets do not support indexed access by design — use contains() to check membership.
Creating
use function Noctud\Collection\setOf;
use function Noctud\Collection\mutableSetOf;
$immutable = setOf(['a', 'b', 'c']);
$mutable = mutableSetOf(['a', 'b', 'c']);
$empty = setOf();
$deduped = setOf([1, 2, 2, 3]); // {1, 2, 3}
$lazy = setOf(fn() => loadUniqueElements());Querying
$set = setOf([1, 2, 3, 4, 5]);
$set->contains(3); // true
$set->containsAll([1, 3]); // true
$set->count(); // 5
$set->isEmpty(); // false
$set->isNotEmpty(); // trueElement Access
Sets support the same access methods as other collections:
$set = setOf([10, 20, 30]);
$set->first(); // 10
$set->last(); // 30
$set->find(fn($n) => $n > 15); // 20 - first match or null
$set->findLast(fn($n) => $n > 15); // 30 - last match or null
$set->expect(fn($n) => $n > 15); // 20 - first match or throws
$set->random(); // random elementTransforming
All transformation methods return immutable collections — the original is never modified, and the result is always immutable regardless of whether the source is mutable or immutable.
$set = mutableSetOf([1, 2, 3, 4, 5]);
$set->filter(fn($n) => $n > 3); // ImmutableSet {4, 5}
$set->map(fn($n) => $n * 2); // ImmutableSet<int>
$set->mapNotNull(fn($n) => $n > 3 ? $n * 2 : null); // ImmutableSet {8, 10}
$set->flatMap(fn($n) => [$n, -$n]); // ImmutableSet<int>
$set->takeFirst(3); // ImmutableSet {1, 2, 3}
$set->takeLast(2); // ImmutableSet {4, 5}
$set->dropFirst(2); // ImmutableSet {3, 4, 5}
$set->dropLast(2); // ImmutableSet {1, 2, 3}
$set->partition(fn($n) => $n % 2 === 0); // [ImmutableSet {2, 4}, ImmutableSet {1, 3, 5}]
$set->groupBy(fn($n) => $n % 2 === 0 ? 'even' : 'odd'); // ImmutableMapAggregation
$set = setOf([3, 1, 4, 5]);
$set->sum(); // 13
$set->avg(); // 3.25
$set->min(); // 1
$set->max(); // 5
$set->reduce(fn($a, $b) => $a + $b); // 13
$set->joinToString(', '); // '3, 1, 4, 5'
$set->joinToString(', ', transform: fn($n) => "#$n"); // '#3, #1, #4, #5'Quantifiers
$set = setOf(['apple', 'avocado', 'banana']);
$set->all(fn($s) => strlen($s) > 3); // true
$set->any(fn($s) => $s[0] === 'b'); // true
$set->none(fn($s) => $s === 'cherry'); // trueMutating (MutableSet)
Mutable methods modify the set in-place. Adding a duplicate element is a no-op:
$set = mutableSetOf(['a', 'b']);
$set->add('c'); // {'a', 'b', 'c'}
$set->add('a'); // no-op - already present
$set->addAll(['d', 'e']); // {'a', 'b', 'c', 'd', 'e'}
$set->removeElement('b'); // {'a', 'c', 'd', 'e'}
$set->removeIf(fn($v) => $v > 'c'); // {'a', 'c'}
$set->removeAll(['a']); // {'c'}
$set->clear(); // {}addFirst - Move to Front
addFirst() guarantees the element is first after the call. If the element already exists in the set, it is moved to the front. If it is already first, the call is a no-op:
$set = mutableSetOf([1, 2, 3]);
$set->addFirst(3); // {3, 1, 2} - moved to front
$set->addFirst(3); // {3, 1, 2} - no-op, already first
$set->addFirst(0); // {0, 3, 1, 2} - new element prependedThis follows the same semantics as Java 21's SequencedSet.addFirst() — the post-condition is that the element is always at the first position, while uniqueness is preserved.
Track changes with tracked():
$tracked = mutableSetOf([1, 2, 3])->tracked();
$tracked->removeElement(99)->changed; // false - not in set
$tracked->removeElement(2)->changed; // trueMutating (ImmutableSet)
Immutable methods return a new set:
$set = setOf([1, 2, 3]);
$new = $set->add(4); // {1, 2, 3, 4}
$new = $set->addFirst(3); // {3, 1, 2} - moved to front
$new = $set->removeElement(2); // {1, 3}
$new = $set->addAll([4, 5]); // {1, 2, 3, 4, 5}
// $set is unchangedSorting
$set = setOf([3, 1, 2]);
$set->sorted(); // {1, 2, 3}
$set->sortedDesc(); // {3, 2, 1}
$set->sortedBy(fn($n) => -$n); // {3, 2, 1}
$set->sortedWith(fn($a, $b) => $a <=> $b); // {1, 2, 3}Mutable sets also support in-place sorting:
$set = mutableSetOf([3, 1, 2]);
$set->sort(); // modifies in placeConversion
Conversion methods return immutable collections:
$set = mutableSetOf([1, 2, 3]);
$set->toArray(); // [1, 2, 3]
$set->toList(); // ImmutableList<int>
$set->toMutable(); // MutableSet<int> (always a new copy)
$set->toImmutable(); // ImmutableSet<int>
$set->toMap(fn($v) => "key_$v"); // ImmutableMap { 'key_1' => 1, ... }
json_encode($set); // [1,2,3]