diff --git a/platform/util/src/com/intellij/util/containers/UnmodifiableHashMap.java b/platform/util/src/com/intellij/util/containers/UnmodifiableHashMap.java index a582b681144a..e927608a80e9 100644 --- a/platform/util/src/com/intellij/util/containers/UnmodifiableHashMap.java +++ b/platform/util/src/com/intellij/util/containers/UnmodifiableHashMap.java @@ -249,6 +249,7 @@ public final @Unmodifiable class UnmodifiableHashMap implements Map<@NotNu * of the resulting map is the same as the strategy of this map. */ public @NotNull UnmodifiableHashMap withAll(@NotNull Map map) { + if (map == this) return this; if (isEmpty()) { return fromMap(strategy, map); } @@ -261,20 +262,31 @@ public final @Unmodifiable class UnmodifiableHashMap implements Map<@NotNu Entry entry = map.entrySet().iterator().next(); return with(entry.getKey(), entry.getValue()); } + Iterator> iterator = map.entrySet().iterator(); + Set> myEntries = entrySet(); + while (iterator.hasNext()) { + Entry entry = iterator.next(); + if (!myEntries.contains(entry)) { + Map newMap; + if (strategy == HashingStrategy.canonical()) { + //noinspection SSBasedInspection + newMap = new Object2ObjectOpenHashMap<>(mapSize + size); + } + else { + // Could be optimized further for map.size() == 2 or 3. + newMap = new Object2ObjectOpenCustomHashMap<>(mapSize + size, getFastutilHashingStrategy(strategy)); + } - Map newMap; - if (strategy == HashingStrategy.canonical()) { - //noinspection SSBasedInspection - newMap = new Object2ObjectOpenHashMap<>(mapSize + size); + newMap.putAll(this); + newMap.put(entry.getKey(), entry.getValue()); + while (iterator.hasNext()) { + entry = iterator.next(); + newMap.put(entry.getKey(), entry.getValue()); + } + return fromMap(strategy, newMap); + } } - else { - // Could be optimized further for map.size() == 2 or 3. - newMap = new Object2ObjectOpenCustomHashMap<>(mapSize + size, getFastutilHashingStrategy(strategy)); - } - - newMap.putAll(this); - newMap.putAll(map); - return fromMap(strategy, newMap); + return this; } private static @NotNull Hash.Strategy getFastutilHashingStrategy(@NotNull HashingStrategy strategy) { @@ -668,6 +680,19 @@ public final @Unmodifiable class UnmodifiableHashMap implements Map<@NotNu @Override public @NotNull Set> entrySet() { return new AbstractSet>() { + @Override + public boolean contains(Object o) { + if (!(o instanceof Entry)) return false; + Entry entry = (Entry)o; + Object key = entry.getKey(); + if (key == null) return false; + V value = get(key); + if (value == null) { + return entry.getValue() == null && containsKey(key); + } + return value.equals(entry.getValue()); + } + @Override public @NotNull Iterator> iterator() { return new MyIterator>() {