Search code examples
javaalgorithmmultimap

Combining Multimaps with respect to Functional Dependencies


Given a multimap, I need to combine the entries with respect to their functional dependencies.

I might have misused the term functional dependency. What I mean is:

If I have three entries of multimap:

a -> b c d

b -> c e f

g -> f h i

I want to combine them as

a -> c e d f

g -> h i

e and f go to a because b is a value of a and c, e, f are values of b.

h and i go to g because neither g nor h are values of a.

f does not go to a because it appears in values of a (priority is ascending).

Here is the code I've written, which gives ConcurrentModificationError:

Multimap<Integer, Integer> map = TreeMultimap.create();
Multimap<Integer, Integer> map2 = TreeMultimap.create();
map.put(0, 1);
map.put(0, 3);
map.put(0, 4);
map.put(1, 3);
map.put(1, 4);
map.put(1, 6);
map.put(3, 7);
map.put(3, 9);
map.put(3, 10);
map.put(2, 7);
map.put(2, 8);
map.put(2, 9);
System.out.println(map);
    for(int i : map.keySet())
    {
        for(int j : map.get(i))
        {
            if(map.containsKey(j))
            {
                Collection<Integer> list = map.get(j);
                map2.putAll(i, map.get(j));
                map.values().removeAll(list);
            }
        }
        if(!map.values().contains(i))
            map2.putAll(i, map.get(i));
    }
System.out.println(map2);

The output is:

{0=[1, 3, 4], 1=[3, 4, 6], 2=[7, 8, 9], 3=[7, 9, 10]}
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.TreeMap$PrivateEntryIterator.nextEntry(Unknown Source)
    at java.util.TreeMap$KeyIterator.next(Unknown Source)
    at com.google.common.collect.AbstractMapBasedMultimap$WrappedCollection$WrappedIterator.next(AbstractMapBasedMultimap.java:486)
    at test.Test.main(Test.java:68)

However, I expect it to be:

{0=[1, 3, 4], 1=[3, 4, 6], 2=[7, 8, 9], 3=[7, 9, 10]}
{0=[1, 3, 4, 6, 7, 9, 10], 2=[8]}

P.S.

A key is always mapped to three values.


Solution

  • You can't iterate over map, and modify it at the same time. The easiest thing you can do to fix your code, is to create a new map as you go through the input rather than modifying the existing one in place.