class MatchedRulesCache {
    private final Map<JmxCollector.Rule, Map<String, MatchedRule>> cachedRules;

    public MatchedRulesCache(Collection<JmxCollector.Rule> rules) {
        this.cachedRules = new HashMap<>(rules.size());
        for (JmxCollector.Rule rule : rules) {
            this.cachedRules.put(rule, new ConcurrentHashMap<>());
        }
    }

    public void put(
            final JmxCollector.Rule rule, final String cacheKey, final MatchedRule matchedRule) {
        Map<String, MatchedRule> cachedRulesForRule = cachedRules.get(rule);
        cachedRulesForRule.put(cacheKey, matchedRule);
    }

    public MatchedRule get(final JmxCollector.Rule rule, final String cacheKey) {
        return cachedRules.get(rule).get(cacheKey);
    }

    // Remove stale rules (in the cache but not collected in the last run of the collector)
    public void evictStaleEntries(final StalenessTracker stalenessTracker) {<FILL_FUNCTION_BODY>}

    public static class StalenessTracker {
        private final Map<JmxCollector.Rule, Set<String>> lastCachedEntries = new HashMap<>();

        public void add(final JmxCollector.Rule rule, final String cacheKey) {
            Set<String> lastCachedEntriesForRule =
                    lastCachedEntries.computeIfAbsent(rule, k -> new HashSet<>());
            lastCachedEntriesForRule.add(cacheKey);
        }

        public boolean contains(final JmxCollector.Rule rule, final String cacheKey) {
            Set<String> lastCachedEntriesForRule = lastCachedEntries.get(rule);
            return (lastCachedEntriesForRule != null)
                    && lastCachedEntriesForRule.contains(cacheKey);
        }

        public long cachedCount() {
            long count = 0;
            for (Set<String> cacheKeys : lastCachedEntries.values()) {
                count += cacheKeys.size();
            }
            return count;
        }
    }
}

        for (Map.Entry<JmxCollector.Rule, Map<String, MatchedRule>> entry :
                cachedRules.entrySet()) {
            JmxCollector.Rule rule = entry.getKey();
            Map<String, MatchedRule> cachedRulesForRule = entry.getValue();

            for (String cacheKey : cachedRulesForRule.keySet()) {
                if (!stalenessTracker.contains(rule, cacheKey)) {
                    cachedRulesForRule.remove(cacheKey);
                }
            }
        }
    
<no_super_class>