Question Java 8 Liste dans la carte


Je veux traduire une liste d'objets dans une carte en utilisant les flux et les lambdas de Java 8.

C'est ainsi que je l'écrirais dans Java 7 et ci-dessous.

private Map<String, Choice> nameMap(List<Choice> choices) {
        final Map<String, Choice> hashMap = new HashMap<>();
        for (final Choice choice : choices) {
            hashMap.put(choice.getName(), choice);
        }
        return hashMap;
}

Je peux le faire facilement en utilisant Java 8 et Guava mais j'aimerais savoir comment le faire sans Guava.

En goyave:

private Map<String, Choice> nameMap(List<Choice> choices) {
    return Maps.uniqueIndex(choices, new Function<Choice, String>() {

        @Override
        public String apply(final Choice input) {
            return input.getName();
        }
    });
}

Et Goyave avec Java 8 lambdas.

private Map<String, Choice> nameMap(List<Choice> choices) {
    return Maps.uniqueIndex(choices, Choice::getName);
}

684
2017-12-03 23:18


origine


Réponses:


Basé sur Collectors Documentation c'est aussi simple que:

Map<String, Choice> result =
    choices.stream().collect(Collectors.toMap(Choice::getName,
                                              Function.identity()));

1031
2017-12-03 23:30



Si votre clé est NE PAS garantie d'être unique pour tous les éléments de la liste, vous devriez le convertir en Map<String, List<Choice>> au lieu d'un Map<String, Choice>

Map<String, List<Choice>> result =
 choices.stream().collect(Collectors.groupingBy(Choice::getName));

205
2017-08-22 18:20



Utilisez getName () comme clé et choisissez lui-même la valeur de la map:

Map<String, Choice> result =
    choices.stream().collect(Collectors.toMap(Choice::getName, c -> c));

107
2018-02-28 07:18



En voici un autre au cas où vous ne voudriez pas utiliser Collectors.toMap ()

Map<String, Choice> result =
   choices.stream().collect(HashMap<String, Choice>::new, 
                           (m, c) -> m.put(c.getName(), c),
                           (m, u) -> {});

11
2018-04-19 18:38



Si cela ne vous dérange pas d'utiliser une librairie tierce (Vavr (anciennement connu sous le nom de Javaslang)) vous pourriez utiliser de puissantes nouvelles collections immuables:

// import javaslang.collection.*;
Map<String, Choice> map = list.toMap(choice -> Tuple.of(choice.getName(), choice));

Il existe également de nombreuses méthodes pour convertir les collections Java en avant et en arrière.

S'il vous plaît lire plus sur le nouvelles collections ici.

Disclaimer: Je suis le créateur de Vavr.


10
2018-02-21 21:59



Si cela ne vous dérange pas d'utiliser des bibliothèques tierces, AOL cyclope-réagit lib (divulgation je suis un contributeur) a des extensions pour tous Collection JDK types, y compris liste et Carte.

ListX<Choices> choices;
Map<String, Choice> map = choices.toMap(c-> c.getName(),c->c);

8
2018-02-24 17:45



Une option de plus de manière simple

Map<String,Choice> map = new HashMap<>();
choices.forEach(e->map.put(e.getName(),e));

8
2018-04-07 07:02



J'essayais de le faire et j'ai trouvé que, en utilisant les réponses ci-dessus, en utilisant Functions.identity() pour la clé de la carte, alors j'ai eu des problèmes avec l'utilisation d'une méthode locale comme this::localMethodName travailler réellement à cause de problèmes de frappe.

Functions.identity() fait réellement quelque chose à la saisie dans ce cas, donc la méthode ne fonctionnerait que par retour Object et en acceptant un param de Object

Pour résoudre cela, j'ai fini par abandonner Functions.identity() et en utilisant s->s au lieu.

Donc mon code, dans mon cas, pour lister tous les répertoires dans un répertoire, et pour chacun utiliser le nom du répertoire comme clé de la map puis appeler une méthode avec le nom du répertoire et retourner une collection d'éléments, ressemble à ceci:

Map<String, Collection<ItemType>> items = Arrays.stream(itemFilesDir.listFiles(File::isDirectory))
.map(File::getName)
.collect(Collectors.toMap(s->s, this::retrieveBrandItems));

7
2018-01-08 10:43