Skip to content

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

php
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

php
$set = setOf([1, 2, 3, 4, 5]);

$set->contains(3); // true
$set->containsAll([1, 3]); // true
$set->count(); // 5
$set->isEmpty(); // false
$set->isNotEmpty(); // true

Element Access

Sets support the same access methods as other collections:

php
$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 element

Transforming

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.

php
$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'); // ImmutableMap

Aggregation

php
$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

php
$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'); // true

Mutating (MutableSet)

Mutable methods modify the set in-place. Adding a duplicate element is a no-op:

php
$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:

php
$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 prepended

This 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():

php
$tracked = mutableSetOf([1, 2, 3])->tracked();
$tracked->removeElement(99)->changed; // false - not in set
$tracked->removeElement(2)->changed; // true

Mutating (ImmutableSet)

Immutable methods return a new set:

php
$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 unchanged

Sorting

php
$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:

php
$set = mutableSetOf([3, 1, 2]);
$set->sort(); // modifies in place

Conversion

Conversion methods return immutable collections:

php
$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]