class ConcurrentHashMultimap implements Multimap<K, V> {

    public boolean removeIf(K key, V value, Predicate<V> match) {
        // this can be updated multiple times by the compute call below. The last write wins. Never rely on its default value.
        final AtomicBoolean modified = new AtomicBoolean(false);
        final Object id = valueIdentityExtractor.apply(value);

        entries.compute(key, (ignored, values) -> {
            if (values == null) {
                modified.set(false);
                return null;
            }
            if (!values.containsKey(id)) {
                modified.set(false);
                return values;
            }
            V currentValue = values.get(id);
            if (!match.test(currentValue)) {
                modified.set(false);
                return values;
            }
            modified.set(true);
            Map<Object, V> newValues = CollectionsExt.copyAndRemove(values, id);
            if (newValues.isEmpty()) {
                return null;
            }
            return newValues;
        });
        return modified.get();
    }

    public  ConcurrentHashMultimap(ValueIdentityExtractor<V> valueIdentityExtractor, ConflictResolver<V> conflictResolver);

}