public static @NotNull <K, V> UnmodifiableHashMap<K, V> fromMap(@NotNull HashingStrategy<K> strategy, @NotNull Map<? extends K, ? extends V> map) {
    //noinspection unchecked
    if (map instanceof UnmodifiableHashMap && ((UnmodifiableHashMap<K, V>)map).strategy == strategy) {
      //noinspection unchecked
      return (UnmodifiableHashMap<K, V>)map;
    }
    else if (map.isEmpty()) {
      return empty(strategy);
    }
    else if (map.size() <= 3) {
      K k1 = null;
      K k2 = null;
      K k3 = null;
      V v1 = null;
      V v2 = null;
      V v3 = null;
      Iterator<? extends Entry<? extends K, ? extends V>> iterator = map.entrySet().iterator();
      if (iterator.hasNext()) {
        Entry<? extends K, ? extends V> e = iterator.next();
        k1 = e.getKey();
        v1 = e.getValue();
        if (iterator.hasNext()) {
          e = iterator.next();
          k2 = e.getKey();
          v2 = e.getValue();
          if (iterator.hasNext()) {
            e = iterator.next();
            k3 = e.getKey();
            v3 = e.getValue();
            assert !iterator.hasNext();
          }
        }
      }
      return new UnmodifiableHashMap<>(strategy, ArrayUtilRt.EMPTY_OBJECT_ARRAY, k1, v1, k2, v2, k3, v3);
    }
    else {
      Object[] newData = new Object[map.size() * 4];
      map.forEach((k, v) -> insert(strategy, newData, Objects.requireNonNull(k), v));
      return new UnmodifiableHashMap<>(strategy, newData, null, null, null, null, null, null);
    }
  }
public static @NotNull <K, V> UnmodifiableHashMap<K, V> fromMap(@NotNull HashingStrategy<K> strategy, @NotNull Map<? extends K, ? extends V> map)