web-dev-qa-db-fra.com

constructeur pour HashMap

Guava nous fournit d'excellentes méthodes d'usine pour les types Java, telles que Maps.newHashMap().

Mais existe-t-il également des constructeurs pour Java Maps?

HashMap<String,Integer> m = Maps.BuildHashMap.
    put("a",1).
    put("b",2).
    build();
95
Elazar Leibovich

HashMaps n'existe pas, mais vous pouvez créer un ImmutableMap avec un générateur:

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

Et si vous avez besoin d'une carte modifiable, vous pouvez simplement l'envoyer au constructeur HashMap.

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

Pas tout à fait un constructeur, mais en utilisant un initialiseur: 

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

Ceci est similaire à la réponse acceptée, mais un peu plus propre, à mon avis:

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

Il existe plusieurs variantes de la méthode ci-dessus et elles sont très utiles pour créer des cartes statiques, immuables et immuables.

34
Jake Toronto

Depuis Java 9 Map l'interface contient:

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

Les limitations de ces méthodes d'usine sont les suivantes:

  • ne peut pas contenir nulls en tant que clés et/ou valeurs (si vous devez stocker des valeurs null, jetez un œil à d'autres réponses)
  • produire des cartes immuables - si nous avons besoin de cartes mutables , nous pouvons utiliser des copies - constructeur de la carte mutable sélectionnée comme HashMap et y passe le résultat de Map.of(..) comme

    Map<Integer, String> map = new HashMap<>( Map.of(1,"a", 2,"b", 3,"c") );
    
8
Pshemo

Un constructeur de carte simple est simple à écrire:

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
Agnes

Vous pouvez utiliser:

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

Ce n'est pas aussi élégant et lisible, mais fait le travail.

6
Elazar Leibovich

Voici un très simple ...

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);
  }
}

puis 

import static FluentHashMap.map;

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

Voir https://Gist.github.com/culmat/a3bcc646fa4401641ac6eb01f3719065

3
culmat

HashMap est mutable; il n'y a pas besoin de constructeur.

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

En voici un que j'ai écrit

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);
    }
}

Vous l'utilisez comme ceci:

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();
0
Dónal

C’est quelque chose que j’ai toujours souhaité, en particulier lors de la configuration des montages de test. Enfin, j’ai décidé d’écrire mon propre constructeur qui parle couramment et qui pourrait créer n’importe quelle implémentation de 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
aathif

J'avais une exigence similaire il y a quelque temps. Cela n’a rien à voir avec Guava, mais vous pouvez faire quelque chose comme ceci pour pouvoir construire proprement une Map en utilisant un constructeur fluide.

Créez une classe de base qui étend 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;
    }
}

Créez ensuite le constructeur fluide avec les méthodes qui répondent à vos besoins:

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...

}

Vous pouvez ensuite l'implémenter comme ceci:

ValueMap map = new ValueMap()
      .withValue("key 1", "value 1")
      .withValue("key 2", "value 2")
      .withValue("key 3", "value 3")
0
tarka