Les objets utilisés dans l'exemple proviennent du package org.jsoup.nodes
import org.jsoup.nodes.Attribute;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
J'ai besoin d'attributs de groupe par clé avec la valeur résultante Set
.
Optional<Element> buttonOpt = ...;
Map<String, Set<String>> stringStringMap =
buttonOpt.map(button -> button.attributes().asList().stream()
.collect(groupingBy(Attribute::getKey,
mapping(attribute -> attribute.getValue(), toSet()))))
.orElse(new HashMap<>());
Il semble collecté correctement, mais la valeur est toujours une chaîne unique (en raison de l'implémentation de la bibliothèque) qui contient différentes valeurs divisées par l'espace. Essayer d'améliorer la solution:
Map<String, Set<HashSet<String>>> stringSetMap = buttonOpt.map(
button -> button.attributes()
.asList()
.stream()
.collect(groupingBy(Attribute::getKey,
mapping(attribute ->
new HashSet<String>(Arrays.asList(attribute.getValue()
.split(" "))),
toSet()))))
.orElse(new HashMap<>());
En conséquence, j'ai une structure différente Map<String, Set<HashSet<String>>>
Mais, j'ai besoin Map<String, Set<String>>
J'ai vérifié certains collectionneurs mais je n'ai pas géré mon problème.
Comment fusionner tous les ensembles liés à la même clé d'attribut?
Vous pouvez diviser vos attributs avec flatMap
et créer de nouvelles entrées à regrouper:
Optional<Element> buttonOpt = ...
Map<String, Set<String>> stringStringMap =
buttonOpt.map(button ->
button.attributes()
.asList()
.stream()
.flatMap(at -> Arrays.stream(at.getValue().split(" "))
.map(v -> new SimpleEntry<>(at.getKey(),v)))
.collect(groupingBy(Map.Entry::getKey,
mapping(Map.Entry::getValue, toSet()))))
.orElse(new HashMap<>());
Voici une façon de faire Java9,
Map<String, Set<String>> stringSetMap = buttonOpt
.map(button -> button.attributes().asList().stream()
.collect(Collectors.groupingBy(Attribute::getKey, Collectors.flatMapping(
attribute -> Arrays.stream(attribute.getValue().split(" ")), Collectors.toSet()))))
.orElse(Collections.emptyMap());
Cela devient moins compliqué si vous utilisez une structure de données plus appropriée, à savoir --- multimap .
Les multi-cartes sont présentes, par exemple in Guava , où vous pouvez le faire comme suit:
SetMultimap<String, String> stringMultimap = buttonOpt
.map(button -> button.attributes().asList().stream()
.collect(ImmutableSetMultimap.flatteningToImmutableSetMultimap(
Attribute::getKey,
attribute -> Arrays.stream(attribute.getValue().split(" "))
))
).orElse(ImmutableSetMultimap.of());
Je l'ai rendu immuable ( ImmutableSetMultimap
), mais une version modifiable peut également être obtenue en utilisant Multimaps.flatteningToMultimap
.