+ /*
+ * The default HashMap copy constructor performs a bad thing for small maps, using the default capacity of 16
+ * as the minimum sizing hint, which can lead to wasted memory. Since the HashMap grows in powers-of-two, we
+ * only kick this in if we are storing 6 entries or less, as that results in 8-entry map -- the next power is
+ * 16, which is the default.
+ */
+ final Map<K, V> ret;
+ final int size = input.size();
+ if (size <= 6) {
+ final int target;
+ switch (size) {
+ case 0:
+ case 1:
+ target = 1;
+ break;
+ case 2:
+ target = 2;
+ break;
+ case 3:
+ target = 4;
+ break;
+ default:
+ target = 8;
+ }
+
+ ret = new HashMap<>(target);
+ ret.putAll(input);
+ } else if (input instanceof HashMap) {
+ // HashMap supports cloning, but we want to make sure we trim it down if entries were removed, so we do
+ // this only after having checked for small sizes.
+ @SuppressWarnings("unchecked")
+ final Map<K, V> tmp = (Map<K, V>) ((HashMap<K, V>) input).clone();
+ ret = tmp;
+ } else {
+ ret = new HashMap<>(input);
+ }