Skip to content

Cheatsheet ​

A scannable, example-driven tour of the API. For exact signatures and edge cases, see the API Reference.

How to read this ​

  • Examples use the factory functions β€” listOf, setOf, mapOf (immutable) and their mutable* variants.
  • Emoji are just sample values; plain numbers appear where the operation is arithmetic.
  • A trailing comment shows the result's contents: [...] is a list, {...} is a set or map.
  • Unless noted, transformation and ordering methods return a new immutable collection β€” the source is never changed, even when it is mutable.
  • Predicates/selectors on List/Set receive (element, int $index); on Map, (value, key).
  • Some examples reuse $isFruit = fn($e) => in_array($e, ['🍎','🍊','πŸ‹','πŸ‡'], true);.

Creating collections ​

php
listOf(['🍎','🍊','πŸ‹']); // ImmutableList
mutableListOf([1, 2, 3]); // MutableList
setOf(['🍎','🍎','🍊']); // ImmutableSet {🍎, 🍊} β€” duplicates dropped
mutableSetOf(['a','b']); // MutableSet
mapOf(['🍎' => 3, '🍌' => 5]); // ImmutableMap (fruit β†’ count)
mutableMapOf(['x' => 10]); // MutableMap

mapOfPairs([['1','a'], [$user,'b']]); // preserves exact key types
stringMapOf(['name' => 'Amy']); // optimized for string keys
intMapOf([1 => 'a', 2 => 'b']); // optimized for int keys

listOf(fn() => loadRows()); // lazy β€” loaded on first access

List & Set ​

Inherited from Collection<E>, so available on both lists and sets.

Element access ​

php
listOf(['🍎','🍊','πŸ‡'])->first(); // 🍎
listOf([])->firstOrNull(); // null
listOf(['🍎','🍊','πŸ‡'])->last(); // πŸ‡
listOf(['🍎'])->single(); // 🍎 β€” throws unless exactly one element
listOf(['🍎','🍊','πŸ‡'])->find($isFruit); // 🍎 (first match)
listOf(['🍎','🍊','πŸ‡'])->findLast($isFruit); // πŸ‡ β€” last match
listOf(['πŸ₯•','πŸ₯¦'])->expect($isFruit); // throws NoSuchElementException
listOf(['🍎','🍊','πŸ‡'])->random(); // e.g. 🍊

Querying ​

php
listOf(['🍎','🍊','πŸ‹'])->contains('🍊'); // true
listOf(['🍎','🍊','πŸ‹'])->containsAll(['🍎','πŸ‹']); // true
listOf(['🍎','🍊'])->all($isFruit); // true
listOf(['🍎','πŸ₯•'])->any($isFruit); // true
listOf(['πŸ₯•','πŸ₯¦'])->none($isFruit); // true
listOf(['🍎','🍊','πŸ‹'])->count(); // 3
listOf(['🍎','πŸ₯•','🍊'])->countWhere($isFruit); // 2
listOf([])->isEmpty(); // true

Aggregation ​

Arithmetic, so these use plain numbers. fold starts from an initial value, reduce from the first element.

php
listOf([1, 2, 3])->fold(10, fn($acc, $n) => $acc + $n); // 16
listOf([1, 2, 3])->reduce(fn($acc, $n) => $acc + $n); // 6
listOf([])->reduceOrNull(fn($a, $b) => $a + $b); // null
listOf([10, 20, 30])->sum(); // 60
listOf([10, 20, 30])->avg(); // 20.0
listOf([3, 1, 2])->min(); // 1
listOf([3, 1, 2])->max(); // 3

min/max return the element; minOf/maxOf return the selector value.

php
$people = listOf([
    ['name' => 'Amy', 'age' => 30],
    ['name' => 'Bob', 'age' => 25],
]);
$people->min(fn($p) => $p['age']); // ['name' => 'Bob', 'age' => 25]
$people->minOf(fn($p) => $p['age']); // 25
php
listOf(['🍎','🍊','πŸ‹'])->joinToString(', '); // "🍎, 🍊, πŸ‹"
listOf(['🍎','🍊'])->joinToString(', ', '[', ']'); // "[🍎, 🍊]"
listOf(['🍎','🍊','🍎'])->countBy(fn($e) => $e); // {🍎: 2, 🍊: 1}

Transformation ​

php
listOf(['🍎','πŸ₯•','🍊','πŸ₯¦'])->filter($isFruit); // [🍎, 🍊]
listOf(['🍎', null, '🍊'])->filterNotNull(); // [🍎, 🍊]
listOf($animals)->filterInstanceOf(Dog::class); // ImmutableList<Dog>
listOf(['πŸ›','πŸ›','πŸ›'])->map(fn($e) => 'πŸ¦‹'); // [πŸ¦‹, πŸ¦‹, πŸ¦‹]
listOf([1, 2, 3, 4])->mapNotNull(fn($n) => $n % 2 ? null : $n); // [2, 4]
listOf([['🍎','🍊'], ['πŸ‹']])->flatMap(fn($g) => $g); // [🍎, 🍊, πŸ‹]
listOf([['🍎','🍊'], ['πŸ‹']])->flatten(); // [🍎, 🍊, πŸ‹]
php
listOf(['🍎','🍊','πŸ‹','πŸ‡'])->takeFirst(2); // [🍎, 🍊]
listOf(['🍎','🍊','πŸ‹','πŸ‡'])->takeLast(2); // [πŸ‹, πŸ‡]
listOf(['🍎','🍊','πŸ‹','πŸ‡'])->dropFirst(2); // [πŸ‹, πŸ‡]
listOf(['🍎','🍊','πŸ‹','πŸ‡'])->dropLast(2); // [🍎, 🍊]

listOf(['🍎','🍊','πŸ₯•','πŸ‹'])->takeWhile($isFruit); // [🍎, 🍊]
listOf(['🍎','🍊','πŸ₯•','πŸ‹'])->dropWhile($isFruit); // [πŸ₯•, πŸ‹]

listOf(['🍎','🍊','🍎','πŸ‹'])->distinct(); // [🍎, 🍊, πŸ‹]
$people->distinctBy(fn($p) => $p['age']); // first of each distinct age

chunked splits into fixed-size pieces; windowed slides a window across.

php
listOf([1, 2, 3, 4, 5])->chunked(2); // [[1,2], [3,4], [5]]
listOf([1, 2, 3, 4])->windowed(2); // [[1,2], [2,3], [3,4]]
listOf([1, 2, 3, 4, 5])->windowed(3, step: 2); // [[1,2,3], [3,4,5]]

zip pairs two lists (stops at the shorter); zipWithNext pairs adjacent elements; unzip is the inverse of zip.

php
listOf(['πŸ§‘','πŸ‘©'])->zip(['🎩','πŸ‘’']); // [[πŸ§‘,🎩], [πŸ‘©,πŸ‘’]]
listOf(['🍎','🍊','πŸ‹'])->zipWithNext(); // [[🍎,🍊], [🍊,πŸ‹]]
listOf([['πŸ§‘','🎩'], ['πŸ‘©','πŸ‘’']])->unzip(); // [[πŸ§‘,πŸ‘©], [🎩,πŸ‘’]]

partition splits into [matching, rest]; groupBy returns a Map of lists.

php
listOf(['🍎','πŸ₯•','🍊','πŸ₯¦'])->partition($isFruit); // [[🍎,🍊], [πŸ₯•,πŸ₯¦]]
listOf([1, 2, 3, 4])->groupBy(fn($n) => $n % 2 ? 'odd' : 'even');
// {odd: [1, 3], even: [2, 4]}

Set operations always return an ImmutableSet.

php
listOf(['🍎','🍊','πŸ‹'])->intersect(['🍊','πŸ‹','πŸ‡']); // {🍊, πŸ‹}
listOf(['🍎','🍊'])->union(['🍊','πŸ‡']); // {🍎, 🍊, πŸ‡}
listOf(['🍎','🍊','πŸ‹'])->subtract(['🍊','πŸ‹']); // {🍎}

Ordering ​

php
listOf([3, 1, 2])->sorted(); // [1, 2, 3]
listOf([3, 1, 2])->sortedDesc(); // [3, 2, 1]
$people->sortedBy(fn($p) => $p['age']); // youngest β†’ oldest
$people->sortedByDesc(fn($p) => $p['age']); // oldest β†’ youngest
listOf([3, 1, 2])->sortedWith(fn($a, $b) => $a <=> $b); // [1, 2, 3]
listOf(['🍎','🍊','πŸ‹'])->reversed(); // [πŸ‹, 🍊, 🍎]
listOf(['🍎','🍊','πŸ‹'])->shuffled(); // random order

Iteration & conversion ​

php
listOf(['🍎','🍊'])->forEach(fn($e) => send($e)); // returns the list

listOf(['🍎','🍊','🍎'])->toSet(); // {🍎, 🍊}
setOf(['🍎','🍊'])->toList(); // [🍎, 🍊]
listOf(['🍎','🍊'])->toArray(); // ['🍎', '🍊'] β€” native PHP array
listOf(['Amy','Bob'])->toMap(fn($n) => $n[0]); // {A: 'Amy', B: 'Bob'}
listOf([1, 2])->toMutable(); // MutableList β€” always a fresh copy
mutableListOf([1, 2])->toImmutable(); // ImmutableList

List only ​

Positional access by integer index (Set has none). slice(from, to) is from-inclusive, to-exclusive.

php
listOf(['🍎','🍊','πŸ‹'])->get(1); // 🍊 β€” alias: $list[1]
listOf(['🍎','🍊','πŸ‹'])->getOrNull(9); // null β€” $list[9] ?? null
listOf(['🍎','🍊'])->getOrDefault(9, '🚫'); // 🚫
listOf(['🍎','🍊','πŸ‹'])->indexOf('🍊'); // 1 (-1 if absent)
listOf([10, 20, 30])->indexOfFirst(fn($n) => $n > 15); // 1
listOf(['🍎','🍊','πŸ‹','πŸ‡'])->slice(1, 3); // [🍊, πŸ‹]

Mutation adds set(index, value), removeAt(index), removeEvery(value).

Set only ​

Sets hold unique elements (duplicates dropped on insert) and add no methods of their own. One twist: addFirst() uses move-to-front semantics.

php
setOf(['🍎','🍎','🍊']); // {🍎, 🍊}
mutableSetOf(['🍎','🍊','πŸ‹'])->addFirst('πŸ‹'); // {πŸ‹, 🍎, 🍊}

Map ​

A key-value collection with strict key handling β€” keys are never silently cast. Predicates receive (value, key).

Keys, values & entries ​

A map exposes three live, read-only views as properties: $keys is a Set, $values is a Collection, and $entries is a Set of MapEntry. Keys are unique (so a Set); values may repeat (so a Collection).

php
$colors = mapOf(['🍎' => 'red', '🍌' => 'yellow', 'πŸ‡' => 'purple']);

$colors->keys; // Set<string> {🍎, 🍌, πŸ‡}
$colors->values; // Collection<string> [red, yellow, purple]
$colors->entries; // Set<MapEntry> {πŸŽβ†’red, πŸŒβ†’yellow, πŸ‡β†’purple}

Split apart, the same map decomposes like this:

$colors entry->keys (Set)->values (Collection)
🍎 β†’ red🍎red
🍌 β†’ yellow🍌yellow
πŸ‡ β†’ purpleπŸ‡purple

Access & querying ​

php
mapOf(['🍎' => 3])->get('🍎'); // 3 β€” alias: $map['🍎']
mapOf(['🍎' => 3])->getOrNull('🍌'); // null
mapOf(['🍎' => 3])->getOrDefault('🍌', 0); // 0
mutableMapOf(['🍎' => 3])->getOrPut('🍌', fn() => 5); // 5 (stored)

mapOf(['🍎' => 3])->containsKey('🍎'); // true
mapOf(['🍎' => 3])->containsValue(3); // true
mapOf(['🍎' => 3, '🍌' => 5])->count(); // 2
mapOf(['🍎' => 3, '🍌' => 5])->all(fn($v, $k) => $v > 0); // true

Transformation ​

php
mapOf(['🍎' => 3, '🍌' => 5])->filter(fn($v, $k) => $v > 4); // {🍌: 5}
mapOf(['🍎' => 3, '🍌' => 5])->filterValues(fn($v) => $v > 4); // {🍌: 5}
mapOf(['🍎' => 3])->mapValues(fn($v, $k) => $v * 10); // {🍎: 30}
mapOf(['🍎' => 3])->mapKeys(fn($v, $k) => "fruit:$k"); // {fruit:🍎: 3}
mapOf(['🍎' => 3, '🍌' => 5])->flip(); // {3: 🍎, 5: 🍌}

mapOf(['🍎' => 3, '🍌' => 5])->map(fn($v, $k) => "$k=$v");
// ['🍎=3', '🍌=5'] β€” a list

Ordering & conversion ​

php
mapOf(['🍌' => 5, '🍎' => 3])->sortedByValue(); // {🍎: 3, 🍌: 5}
mapOf(['🍌' => 5, '🍎' => 3])->reversed(); // {🍎: 3, 🍌: 5}
mapOf(['🍎' => 3])->toArray(); // ['🍎' => 3]
mapOf(['🍎' => 3])->toPairs(); // [['🍎', 3]]

Mutation ​

php
mutableMapOf(['🍎' => 3])->put('🍌', 5); // adds/replaces
mutableMapOf(['🍎' => 3])->putIfAbsent('🍎', 9); // no-op β€” key exists
mutableMapOf(['🍎' => 3, '🍌' => 5])->remove('🍎'); // {🍌: 5}

Also: putFirst, putAll, putAllPairs, removeIf, removeIfKey, removeIfValue, removeNullValues, clear, plus the in-place sortByKey / sortByValue / … family.

Mutable vs. immutable ​

Same method names, different behavior. On a mutable collection they change it in place and return it (handy for chaining); on an immutable collection they return a new collection and leave the original untouched.

php
$m = mutableListOf(['🍎','🍊']);
$m->add('πŸ‹'); // $m is now [🍎, 🍊, πŸ‹]

$i = listOf(['🍎','🍊']);
$new = $i->add('πŸ‹'); // $i stays [🍎, 🍊]; $new is [🍎, 🍊, πŸ‹]

Shared mutators (List & Set): add, addFirst, addAll, removeElement, removeFirst, removeLast, removeIf, removeAll, retainAll, clear, and the in-place ordering sort / sortBy / sortByDesc / sortWith / reverse / shuffle.

Tracking changes ​

tracked() wraps a mutable collection so each mutation reports whether it actually changed anything:

php
$t = mutableSetOf(['🍎','🍊'])->tracked();
$t->add('πŸ‹')->changed; // true
$t->add('πŸ‹')->changed; // false β€” already present