public @NotNull UnmodifiableHashMap<K, V> withAll(@NotNull Map<? extends K, ? extends V> map) {
    if (isEmpty()) {
      return fromMap(strategy, map);
    }

    int mapSize = map.size();
    if (mapSize == 0) {
      return this;
    }
    else if (mapSize == 1) {
      Entry<? extends K, ? extends V> entry = map.entrySet().iterator().next();
      return with(entry.getKey(), entry.getValue());
    }

    Map<K, V> 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));
    }

    newMap.putAll(this);
    newMap.putAll(map);
    return fromMap(strategy, newMap);
  }
public @NotNull UnmodifiableHashMap<K, V> withAll(@NotNull Map<? extends K, ? extends V> map)