例で使用されているオブジェクトはパッケージorg.jsoup.nodes
からのものです
import org.jsoup.nodes.Attribute;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
結果の値が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<>());
正しく収集されているようですが、常に値は単一の文字列(ライブラリの実装のため)であり、スペースで分割されたさまざまな値が含まれています。ソリューションを改善しようとしています:
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<>());
その結果、異なる構造Map<String, Set<HashSet<String>>>
を取得しましたが、Map<String, Set<String>>
が必要です
一部のコレクターを確認しましたが、問題は解決していません。
同じ属性キーに関連するすべてのセットをマージするにはどうすればよいですか?
属性をflatMap
で分割し、新しいエントリを作成してグループ化できます。
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<>());
これを行う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());
より適切なデータ構造、つまり multimap を使用すると、これはそれほど複雑ではなくなります。
マルチマップが存在します。 Guava では、次のように実行できます。
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());
私はそれを不変にしました( ImmutableSetMultimap
)が、可変バージョンは Multimaps.flatteningToMultimap
。