HashMap的构建器

问题描述 投票:102回答:11

Guava为Java类型提供了很好的工厂方法,例如Maps.newHashMap()

但是还有java Maps的构建者吗?

HashMap<String,Integer> m = Maps.BuildHashMap.
    put("a",1).
    put("b",2).
    build();
java collections guava
11个回答
8
投票

由于Java 9 Map接口包含:

  • Map.of(k1,v1, k2,v2, ..)
  • Map.ofEntries(Map.entry(k1,v1), Map.entry(k2,v2), ..)

这些工厂方法的局限性在于它们:

  • 不能将nulls保存为键和/或值(如果需要存储空值,请查看其他答案)
  • 生成不可变映射 - 如果我们需要可变映射,我们可以使用选定的可变映射的复制构造函数,如HashMap,并传递Map.of(..)的结果 Map<Integer, String> map = new HashMap<>( Map.of(1,"a", 2,"b", 3,"c") );

0
投票

这是我一直想要的,特别是在设置测试夹具时。最后,我决定写一个我自己的简单流利的构建器,可以构建任何Map实现 - https://gist.github.com/samshu/b471f5a2925fa9d9b718795d8bbdfe42#file-mapbuilder-java

    /**
     * @param mapClass Any {@link Map} implementation type. e.g., HashMap.class
     */
    public static <K, V> MapBuilder<K, V> builder(@SuppressWarnings("rawtypes") Class<? extends Map> mapClass)
            throws InstantiationException,
            IllegalAccessException {
        return new MapBuilder<K, V>(mapClass);
    }

    public MapBuilder<K, V> put(K key, V value) {
        map.put(key, value);
        return this;
    }

    public Map<K, V> build() {
        return map;
    }

0
投票

这是我写的一个

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

public class MapBuilder<K, V> {

    private final Map<K, V> map;

    /**
     * Create a HashMap builder
     */
    public MapBuilder() {
        map = new HashMap<>();
    }

    /**
     * Create a HashMap builder
     * @param initialCapacity
     */
    public MapBuilder(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }

    /**
     * Create a Map builder
     * @param mapFactory
     */
    public MapBuilder(Supplier<Map<K, V>> mapFactory) {
        map = mapFactory.get();
    }

    public MapBuilder<K, V> put(K key, V value) {
        map.put(key, value);
        return this;
    }

    public Map<K, V> build() {
        return map;
    }

    /**
     * Returns an unmodifiable Map. Strictly speaking, the Map is not immutable because any code with a reference to
     * the builder could mutate it.
     *
     * @return
     */
    public Map<K, V> buildUnmodifiable() {
        return Collections.unmodifiableMap(map);
    }
}

你这样使用它:

Map<String, Object> map = new MapBuilder<String, Object>(LinkedHashMap::new)
    .put("event_type", newEvent.getType())
    .put("app_package_name", newEvent.getPackageName())
    .put("activity", newEvent.getActivity())
    .build();

157
投票

HashMaps没有这样的东西,但您可以使用构建器创建ImmutableMap:

final Map<String, Integer> m = ImmutableMap.<String, Integer>builder().
      put("a", 1).
      put("b", 2).
      build();

如果你需要一个可变的地图,你可以将它提供给HashMap构造函数。

final Map<String, Integer> m = Maps.newHashMap(
    ImmutableMap.<String, Integer>builder().
        put("a", 1).
        put("b", 2).
        build());

43
投票

不是一个构建器,而是使用初始化器:

Map<String, String> map = new HashMap<String, String>() {{
    put("a", "1");
    put("b", "2");
}};

36
投票

这与接受的答案类似,但在我看来有点干净:

ImmutableMap.of("key1", val1, "key2", val2, "key3", val3);

上述方法有几种变体,它们非常适合制作静态,不变,不可变的地图。


8
投票

一个简单的地图构建器很容易写:

public class Maps {

    public static <Q,W> MapWrapper<Q,W> map(Q q, W w) {
        return new MapWrapper<Q, W>(q, w);
    }

    public static final class MapWrapper<Q,W> {
        private final HashMap<Q,W> map;
        public MapWrapper(Q q, W w) {
            map = new HashMap<Q, W>();
            map.put(q, w);
        }
        public MapWrapper<Q,W> map(Q q, W w) {
            map.put(q, w);
            return this;
        }
        public Map<Q,W> getMap() {
            return map;
        }
    }

    public static void main(String[] args) {
        Map<String, Integer> map = Maps.map("one", 1).map("two", 2).map("three", 3).getMap();
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
    }
}

7
投票

这是一个非常简单的...

public class FluentHashMap<K, V> extends java.util.HashMap<K, V> {
  public FluentHashMap<K, V> with(K key, V value) {
    put(key, value);
    return this;
  }

  public static <K, V> FluentHashMap<K, V> map(K key, V value) {
    return new FluentHashMap<K, V>().with(key, value);
  }
}

然后

import static FluentHashMap.map;

HashMap<String, Integer> m = map("a", 1).with("b", 2);

https://gist.github.com/culmat/a3bcc646fa4401641ac6eb01f3719065


6
投票

您可以使用:

HashMap<String,Integer> m = Maps.newHashMap(
    ImmutableMap.of("a",1,"b",2)
);

它不是那么优雅和可读,而是工作。


4
投票

HashMap是可变的;没有建筑师的需要。

Map<String, Integer> map = Maps.newHashMap();
map.put("a", 1);
map.put("b", 2);

0
投票

我有一段时间有类似的要求。它与番石榴没有任何关系,但你可以做这样的事情,以便能够使用流利的建设者干净地建造一个Map

创建一个扩展Map的基类。

public class FluentHashMap<K, V> extends LinkedHashMap<K, V> {
    private static final long serialVersionUID = 4857340227048063855L;

    public FluentHashMap() {}

    public FluentHashMap<K, V> delete(Object key) {
        this.remove(key);
        return this;
    }
}

然后使用适合您需求的方法创建流畅的构建器:

public class ValueMap extends FluentHashMap<String, Object> {
    private static final long serialVersionUID = 1L;

    public ValueMap() {}

    public ValueMap withValue(String key, String val) {
        super.put(key, val);
        return this;
    }

... Add withXYZ to suit...

}

然后,您可以像这样实现它:

ValueMap map = new ValueMap()
      .withValue("key 1", "value 1")
      .withValue("key 2", "value 2")
      .withValue("key 3", "value 3")
© www.soinside.com 2019 - 2024. All rights reserved.