我有一个带有列表的类Element,我的预期输出是这样的:
Map<String , List<Element>>
{
1 = [Element3, Element1],
2 = [Element2, Element1],
3 = [Element2, Element1], 4=[Element2]
}
我的输入是一组元素对象,我使用forEach
来获得所需的结果,但我正在寻找如何使用collectors.toMap
来收集它。非常感谢任何投入
Set<Element> changes = new HashSet();
List<String> interesetList = new ArrayList();
interesetList.add("1");
interesetList.add("2");
interesetList.add("3");
Element element = new Element(interesetList);
changes.add(element);
interesetList = new ArrayList();
interesetList.add("2");
interesetList.add("3");
interesetList.add("4");
element = new Element(interesetList);
changes.add(element);
Map<String, List<Element>> collect2 = new HashMap();
changes.forEach(element -> {
element.getInterestedList().forEach(tracker -> {
collect2.compute(tracker, ( key , val) -> {
List<Element> elementList = val == null ? new ArrayList<Element>() : val;
elementList.add(Element);
return elementList;
});
});
});
class Element {
List<String> interestedList;
static AtomicInteger sequencer = new AtomicInteger(0);
String mName;
public Element(List<String> aList) {
interestedList = aList;
mName = "Element" + sequencer.incrementAndGet();
}
public List<String> getInterestedList() {
return interestedList;
}
@Override
public String toString() {
return mName;
}
}
答案 0 :(得分:2)
您可以使用Collectors.groupingBy
代替Collectors.toMap
以及Collectors.mapping
来执行此操作,这会将收集器调整为另一个收集器:
Map<String, List<Element>> result = changes.stream()
.flatMap(e -> e.getInterestedList().stream().map(t -> Map.entry(t, e)))
.collect(Collectors.groupingBy(
Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
首先需要使用Stream.flatMap
方法,然后将内部列表的元素与当前Element
实例配对。我是通过新的Java 9 Map.entry(key, value)
方法完成的。如果您尚未使用Java 9,则可以将其更改为new AbstractMap.SimpleEntry<>(key, value)
。
平面映射后,我们需要收集Map.Entry
的实例。因此,我使用Collectors.groupingBy
按键对条目进行分类(我们之前已经存储了内部列表的每个元素,也就是您在代码中称为tracker
的内容)。然后,由于我们不希望将List<Map.Entry<String, Element>>
的实例作为地图的值,我们需要将流的每个Map.Entry<String, Element>
转换为Element
(&#39} ;为什么我使用Map.Entry::getValue
作为Collectors.mapping
的第一个参数。我们还需要指定一个下游收集器(此处为Collectors.toList()
),以便外部Collectors.groupingBy
收集器知道将流的所有适配元素放在哪里,属于每个组。
更短且更有效的方法(类似于您的尝试)可能是:
Map<String, List<Element>> result = new HashMap<>();
changes.forEach(e ->
e.getInterestedList().forEach(t ->
result.computeIfAbsent(t, k -> new ArrayList<>()).add(e)));
这使用Map.computeIfAbsent
,这非常适合您的用例。