public function remove($key, callable $beforeRemove = null)
    {
        // check if a key has been passed
        if (is_null($key)) {
            throw new NullPointerException('Passed key is null');
        }
        // check if a primitive datatype is passed
        if (is_integer($key) || is_string($key) || is_double($key) || is_bool($key)) {
            if (array_key_exists($key, $this->items)) {
                // invoke the callback before
                if (is_callable($beforeRemove)) {
                    call_user_func($beforeRemove, $this->items[$key]);
                }
                // remove the item
                unset($this->items[$key]);
                // remove the lifetime if set
                if (isset($this->lifetime[$key])) {
                    unset($this->lifetime[$key]);
                }
                return;
            } else {
                throw new IndexOutOfBoundsException('Index ' . $key . ' out of bounds');
            }
        }
        // check if an object is passed
        if (is_object($key)) {
            if ($key instanceof String) {
                $newKey = $key->stringValue();
            } elseif ($key instanceof Float) {
                $newKey = $key->floatValue();
            } elseif ($key instanceof Integer) {
                $newKey = $key->intValue();
            } elseif ($key instanceof Boolean) {
                $newKey = $key->booleanValue();
            } elseif (method_exists($key, '__toString')) {
                $newKey = $key->__toString();
            } else {
                throw new InvalidKeyException('Passed key has to be a primitive datatype or ' . 'has to implement the __toString() method');
            }
            if (array_key_exists($newKey, $this->items)) {
                // invoke the callback before
                if (is_callable($beforeRemove)) {
                    call_user_func($beforeRemove, $this->items[$newKey]);
                }
                // remove the item
                unset($this->items[$newKey]);
                // remove the lifetime if set
                if (isset($this->lifetime[$newKey])) {
                    unset($this->lifetime[$newKey]);
                }
                return;
            } else {
                throw new IndexOutOfBoundsException('Index ' . $newKey . ' out of bounds');
            }
        }
        throw new InvalidKeyException('Passed key has to be a primitive datatype or ' . 'has to implement the __toString() method');
    }