public static <K extends Serializable, V, C extends Collection<V> & Serializable> Map<Boolean,Map<K, C>> retainValueInMultiValuedCache( Cache<K, C> cache, V element )
    {
        // In some cache implementations, the entry-set is unmodifiable. To guard against potential
        // future changes of this implementation (that would make the implementation incompatible with
        // these cache implementations), the entry-set that's operated on in this implementation is
        // explicitly wrapped in an unmodifiable collection. That forces this implementation to be
        // compatible with the 'lowest common denominator'.
        final Set<Map.Entry<K, C>> entries = Collections.unmodifiableSet( cache.entrySet() );

        // contains all entries that were somehow changed.
        final Map<Boolean, Map<K, C>> result = new HashMap<>();
        result.put( false, new HashMap<>());
        result.put( true, new HashMap<>());

        for ( final Map.Entry<K, C> entry : entries )
        {
            final K key = entry.getKey();

            final Lock lock = cache.getLock( key );
            lock.lock();
            try
            {
                final C elements = entry.getValue();

                // Remove all instances of the element from the entry value.
                boolean changed = false;
                while ( elements.retainAll( Collections.singleton( element ) ) )
                {
                    changed = true;
                }

                if ( changed )
                {
                    if ( elements.isEmpty() )
                    {
                        // When after removal, the value is empty, remove the cache entry completely.
                        cache.remove( entry.getKey() );
                        result.get(false).put( entry.getKey(), elements );
                    }
                    else
                    {
                        // The cluster-based cache needs an explicit 'put' to cause the change to propagate.
                        cache.put( entry.getKey(), elements );
                        result.get(true).put( entry.getKey(), elements );
                    }
                }
            }
            finally
            {
                lock.unlock();
            }
        }
        return result;
    }
Remove elements from every collection that is a value of the cache, except for the specified element.

When removal leaves a collection empty, the cache entry is removed completely.

The implementation of this method is designed to be compatible with both clustered as well as non-clustered caches.

The return value is a Map that contains all entries that were affected by the call. The returned has exactly two
keys, that each have a Map for its value.
- the Map that is the value of the 'false' key contains all entries that have been removed from the cache.
- the Map that is the value of the 'true' key contains all entries that have been modified.

@param cache   The cache in which to retain the element (cannot be null).
@param element The element to be retained (can be null only if the value-Collection supports null values).
@param <K> the type of key contained by the cache
@param <V> the type of value contained by the cache
@param <C> the type of collection contained by the cache
@return a map containing all affected cache entries (never null)
xmppserver/src/main/java/org/jivesoftware/util/cache/CacheUtil.java