$keys */ private function __construct( private array $keys ) { } /** * Create from CacheKeys using spread operator */ public static function fromKeys(CacheKey ...$keys): self { return new self($keys); } /** * Create empty collection */ public static function empty(): self { return new self([]); } /** * Get all keys as array * @return array */ public function getKeys(): array { return $this->keys; } /** * Get first key or null if empty */ public function first(): ?CacheKey { return $this->keys[0] ?? null; } /** * Get last key or null if empty */ public function last(): ?CacheKey { return end($this->keys) ?: null; } /** * Check if collection contains specific key */ public function contains(CacheKey $key): bool { foreach ($this->keys as $existingKey) { if ($existingKey->equals($key)) { return true; } } return false; } /** * Filter keys by predicate */ public function filter(callable $predicate): self { $filtered = array_filter($this->keys, $predicate); return new self(array_values($filtered)); } /** * Map over keys */ public function map(callable $mapper): self { $mapped = array_map($mapper, $this->keys); return new self($mapped); } /** * Add another key collection */ public function merge(self $other): self { return new self(array_merge($this->keys, $other->keys)); } /** * Add a single key */ public function add(CacheKey $key): self { return new self([...$this->keys, $key]); } /** * Remove duplicates based on string representation */ public function unique(): self { $unique = []; $seen = []; foreach ($this->keys as $key) { $keyString = $key->toString(); if (! isset($seen[$keyString])) { $unique[] = $key; $seen[$keyString] = true; } } return new self($unique); } /** * Check if collection is empty */ public function isEmpty(): bool { return empty($this->keys); } /** * Get keys as string array * @return array */ public function toStringArray(): array { return array_map(fn (CacheKey $key) => $key->toString(), $this->keys); } /** * Countable implementation */ public function count(): int { return count($this->keys); } /** * IteratorAggregate implementation * @return Traversable */ public function getIterator(): Traversable { foreach ($this->keys as $key) { yield $key; } } }