code: void retainRecentAndKnownItems(Collection<String> users, Collection<String> items) {
      // Keep all users in the new model, or, that have been added since last model
      MutableSet<String> recentUserIDs = UnifiedSet.newSet();
      X.addAllRecentTo(recentUserIDs);
      try (AutoLock al = knownItemsLock.autoWriteLock()) {
        knownItems.keySet().removeIf(key -> !users.contains(key) && !recentUserIDs.contains(key));
      }
  
      // This will be easier to quickly copy the whole (smallish) set rather than
      // deal with locks below
      MutableSet<String> allRecentKnownItems = UnifiedSet.newSet();
      Y.addAllRecentTo(allRecentKnownItems);
  
      Predicate<String> notKeptOrRecent = value -> !items.contains(value) && !allRecentKnownItems.contains(value);
      try (AutoLock al = knownItemsLock.autoReadLock()) {
        knownItems.values().forEach(knownItemsForUser -> {
          synchronized (knownItemsForUser) {
            knownItemsForUser.removeIf(notKeptOrRecent);
          }
        });
      }
    }
docs: Like {@link #retainRecentAndUserIDs(Collection)} and {@link #retainRecentAndItemIDs(Collection)}
  but affects the known-items data structure.
  
  @param users users that should be retained, which are coming in the new model updates
  @param items items that should be retained, which are coming in the new model updates