Слияние Карт, содержащих Наборы, выбрасывает UnsupportedOperationException

Вот код:

private static Map<String, Set<String>> merge(Map<String, Set<String>> m1, Map<String, Set<String>> m2) {
    Map<String, Set<String>> mx = new HashMap<String, Set<String>>();
    for (Entry<String, Set<String>> entry : m1.entrySet()) {
        Set<String> otherMapValue = m2.get(entry.getKey());
        if (otherMapValue == null) {
            mx.entrySet().add(entry);
        } else {
            Set<String> merged = new HashSet<String>();
            merged.addAll(entry.getValue());
            merged.addAll(otherMapValue);
            mx.put(entry.getKey(), merged);
        }
    }
    return mx;
}

Это выдает следующую ошибку:

Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractCollection.add(Unknown Source)
at algorithms.NetworkBuilder.merge(NetworkBuilder.java:86)
at algorithms.NetworkBuilder.build(NetworkBuilder.java:38)
at algorithms.Main.main(Main.java:35)

Я нашел только решения с картами, которые не содержат коллекций, они не сработали для меня, так как мне также нужно объединить наборы, если ключ присутствует на обеих картах.
Я хочу создать новую карту, в которой каждый ключ, содержащий одну или обе карты, сопоставляется с объединением списков, в которые он отображается в исходных двух картах.

2 ответа

Решение

Map::entrySet:

Возвращает представление Set отображений, содержащихся в этой карте. [...] Набор поддерживает удаление элементов, которое удаляет соответствующее отображение с карты с помощью операций Iterator.remove, Set.remove, removeAll, retainAll и clear. Он не поддерживает операции добавления или добавления.

Пытаться mx.put(entry.getKey(), entry.getValue()) вместо mx.entrySet().add(entry),

Если вам разрешено использовать сторонние библиотеки, рассмотрите возможность использования Guava Multimap,

Сравнение Multimap s] к карте коллекций

Multimap s обычно используются в местах, где Map<K, Collection<V>> в противном случае появился бы.

Multimap<String, String> m1 = ...
Multimap<String, String> m2 = ...

m1.putAll(m2); // merged!

Проблема вашего кода в строке

mx.entrySet().add(entry);

Используемый вами набор поддерживает только операции удаления: http://docs.oracle.com/javase/7/docs/api/java/util/Map.html

Вы можете изменить эту строку на

mx.put(entry.getKey(), entry.getValue());

Кроме того, ваш метод не учитывает ключи, которые находятся в m2 но не в m1, Вы можете перебрать m2.entrySet() также.

Другие вопросы по тегам