Java列表地图的流图
Java stream map of map of list
我有一个看起来像这样的实体:
public class Snippet {
private Integer docId;
private Integer page;
private Payload payload;
}
输入数据是List<Snippet>
我需要创建一个索引,使我们能够遍历 docId 和页面并获取关联的 Snippet 对象。
所以这样的数据结构:
Map<Integer, Map<Integer, List<Snippet>>>
我可以使用 Java 流来获取 Map> - 但最后不会收集 Snippet 列表。
List<Snippet> input = ....;
input.stream()
.collect(Collectors.groupingBy(
Snippet::getDocId,
Collectors.toMap(Snippet::getPage, Function.identity())
)
);
如何收集得到一个列表作为最终的地图值?
如您所见,Collectors.groupingBy(..)
将收集器作为第二个参数。所以,只需使用 Collectors.groupingBy(..)
作为 Collectors.groupingBy(..)
的第二个参数
input.stream().collect(Collectors.groupingBy(
Snippet::getDocId,
Collectors.groupingBy(Snippet::getPage,
Collectors.toList())));
这是您当前或未来考虑的另一种选择。它使用 Map Interface.
的 computeIfAbsent
方法
- 创建最终的内容地图。
- 遍历
Snippets
的列表
- 如果
DocId
不存在,则创建以 DocId
作为键的条目。然后尝试存储 page
和 Snippet
- 如果
page
不存在,则创建以 page
作为关键字的条目。然后将 Snippet
存储在列表中。
这是一个使用记录代替 类 的示例。
record PayLoad(String getValue) {
@Override
public String toString() {
return "[" + getValue() + "]";
}
}
record Snippet(int getDocId, int getPage,
PayLoad getPayLoad) {
@Override
public String toString() {
return String.format("{%s, %s, %s}", getDocId,
getPage, getPayLoad);
}
}
创建一些数据
List<Snippet> input =
List.of(new Snippet(1, 1, new PayLoad("A")),
new Snippet(1, 2, new PayLoad("B")),
new Snippet(1, 3, new PayLoad("C")),
new Snippet(2, 1, new PayLoad("D")),
new Snippet(2, 2, new PayLoad("E")),
new Snippet(2, 3, new PayLoad("F")));
存储片段
Map<Integer, Map<Integer, List<Snippet>>> map =
new HashMap<>();
for (Snippet s : input) {
map.computeIfAbsent(s.getDocId(), v -> new HashMap<>())
.computeIfAbsent(s.getPage(),
v -> new ArrayList<>())
.add(s);
}
打印它们
map.forEach((k, v) -> {
System.out.println(k);
v.forEach((kk, vv) -> System.out
.println(" " + kk + " -> " + vv));
});
打印
1
1 -> [{1, 1, [A]}]
2 -> [{1, 2, [B]}]
3 -> [{1, 3, [C]}]
2
1 -> [{2, 1, [D]}]
2 -> [{2, 2, [E]}]
3 -> [{2, 3, [F]}]
我有一个看起来像这样的实体:
public class Snippet {
private Integer docId;
private Integer page;
private Payload payload;
}
输入数据是List<Snippet>
我需要创建一个索引,使我们能够遍历 docId 和页面并获取关联的 Snippet 对象。
所以这样的数据结构:
Map<Integer, Map<Integer, List<Snippet>>>
我可以使用 Java 流来获取 Map
List<Snippet> input = ....;
input.stream()
.collect(Collectors.groupingBy(
Snippet::getDocId,
Collectors.toMap(Snippet::getPage, Function.identity())
)
);
如何收集得到一个列表作为最终的地图值?
如您所见,Collectors.groupingBy(..)
将收集器作为第二个参数。所以,只需使用 Collectors.groupingBy(..)
作为 Collectors.groupingBy(..)
input.stream().collect(Collectors.groupingBy(
Snippet::getDocId,
Collectors.groupingBy(Snippet::getPage,
Collectors.toList())));
这是您当前或未来考虑的另一种选择。它使用 Map Interface.
的computeIfAbsent
方法
- 创建最终的内容地图。
- 遍历
Snippets
的列表
- 如果
DocId
不存在,则创建以DocId
作为键的条目。然后尝试存储page
和Snippet
- 如果
page
不存在,则创建以page
作为关键字的条目。然后将Snippet
存储在列表中。
这是一个使用记录代替 类 的示例。
record PayLoad(String getValue) {
@Override
public String toString() {
return "[" + getValue() + "]";
}
}
record Snippet(int getDocId, int getPage,
PayLoad getPayLoad) {
@Override
public String toString() {
return String.format("{%s, %s, %s}", getDocId,
getPage, getPayLoad);
}
}
创建一些数据
List<Snippet> input =
List.of(new Snippet(1, 1, new PayLoad("A")),
new Snippet(1, 2, new PayLoad("B")),
new Snippet(1, 3, new PayLoad("C")),
new Snippet(2, 1, new PayLoad("D")),
new Snippet(2, 2, new PayLoad("E")),
new Snippet(2, 3, new PayLoad("F")));
存储片段
Map<Integer, Map<Integer, List<Snippet>>> map =
new HashMap<>();
for (Snippet s : input) {
map.computeIfAbsent(s.getDocId(), v -> new HashMap<>())
.computeIfAbsent(s.getPage(),
v -> new ArrayList<>())
.add(s);
}
打印它们
map.forEach((k, v) -> {
System.out.println(k);
v.forEach((kk, vv) -> System.out
.println(" " + kk + " -> " + vv));
});
打印
1
1 -> [{1, 1, [A]}]
2 -> [{1, 2, [B]}]
3 -> [{1, 3, [C]}]
2
1 -> [{2, 1, [D]}]
2 -> [{2, 2, [E]}]
3 -> [{2, 3, [F]}]