class EntryComparator implements Comparator<Entry<V, K>>
    {
        @Override
        public int compare(Entry<V, K> first, Entry<V, K> second)
        {
            return first.getValue().compareTo(second.getValue());
        }
    }

    private final Comparator<? super Entry<V, K>> comparator = new EntryComparator();

    // where all the data will be put
    private final Map<K, List<V>> data;
    // inverse mapping to speed-up the process
    private final Map<V, K> inverse;

    public MultiMap()
    {
        data = new HashMap<>();
        inverse = new HashMap<>();
    }

    public void clear()
    {
        data.clear();
        inverse.clear();
    }

    public Collection<Entry<V, K>> entries()
    {
        List<Entry<V, K>> list = new ArrayList<>(inverse.entrySet());
        list.sort(comparator);
        return list;
    }

    @Deprecated
    public Collection<V> values()
    {
        return inverse.keySet();
    }

    public boolean contains(V value)
    {
        return inverse.containsKey(value);
    }

    public K key(V value)
    {
        return inverse.get(value);
    }

    public V find(V copy)
    {
        K key = inverse.get(copy);
        if (key != null) {
            List<V> list = data.get(key);
            return list.get(list.indexOf(copy));
        }
        return null;
    }

    public boolean hasValues(K key)
    {
        List<V> list = data.get(key);
        if (list == null) {
            return false;
        }
        return !list.isEmpty();
    }

    public boolean isEmpty()
    {
        return inverse.isEmpty();
    }

    private List<V> getValues(K key)
    {
        return data.computeIfAbsent(key, k -> new ArrayList<>());
    }

    public boolean insert(K key, V value)
    {
        K old = inverse.get(value);
        if (old != null) {
            boolean rc = removeData(old, value);
            assert rc;
        }
        boolean inserted = getValues(key).add(value);
        if (inserted) {
            inverse.put(value, key);
        }
        else {
            inverse.remove(value);
        }
        return inserted;
    }

    public Collection<V> remove(K key)
    {<FILL_FUNCTION_BODY>

        List<V> removed = data.remove(key);
        if (removed != null) {
            for (V val : removed) {
                inverse.remove(val);
            }
        }
        return removed;
    
<no_super_class>