@Nonnull
    @Override
    public ImmutableUserAgent parse(MutableUserAgent userAgent) {
        // Many caching implementations do not allow null keys and/or values
        if (userAgent == null || userAgent.getUserAgentString() == null) {
            synchronized (this) {
                if (nullAgent == null) {
                    nullAgent = super.parse(new MutableUserAgent((String) null));
                }
                return nullAgent;
            }
        }

        // Do we even have a cache?
        if (parseCache == null) {
            return super.parse(userAgent);
        }

        String cachingKey = userAgent.getUserAgentString();

        if (userAgent.getHeaders().size() > 1) {
            // We must sanitise all client headers because these are the caching key.
            Map<String, String> cleanedHeaders = new TreeMap<>(); // Ordered --> predicatable
            cleanedHeaders.put(USERAGENT_HEADER, userAgent.getUserAgentString());
            for (Map.Entry<String, String> entry : userAgent.getHeaders().entrySet()) {
                String headerName = entry.getKey();
                if (isSupportedClientHintHeader(headerName)) {
                    cleanedHeaders.put(headerName.toLowerCase(Locale.ROOT), entry.getValue());
                }
            }
            userAgent.setHeaders(cleanedHeaders);
            cachingKey = userAgent.getHeaders().toString();
        }

        // As the parse result is immutable it can safely be cached and returned as is
        return parseCache.computeIfAbsent(cachingKey, ua -> super.parse(userAgent));
    }
A single method that must create a new instance of the cache.
The returned instance MUST implement at least the {@link Map#get} and {@link Map#put}
methods in a threadsafe way if you intend to use this in a multithreaded scenario.
Yauaa only uses the put and get methods and in exceptional cases the clear method.
An implementation that does some kind of automatic cleaning of obsolete values is recommended (like LRU).
@param cacheSize is the size of the new cache (which will be >= 1)
@return Instance of the new cache.
analyzer/src/main/java/nl/basjes/parse/useragent/AbstractUserAgentAnalyzer.java