从c#迁移到Java方面,我还很陌生。我有以下课程。
class Resource {
String name;
String category;
String component;
String group;
}
我想知道以下数字: 1.类别中的资源计数。 2.每个类别中组件的不同数量。 (组件名称可以重复) 3.按类别和组分组的资源计数。
使用Collectors.groupingBy
可以取得一些成功。但是结果总是这样。
Map<String, List<Resource>>
要获得计数,我必须解析键集并计算大小。 使用c#linq,我可以轻松计算上述所有指标。 我假设在Java中肯定还有更好的方法可以做到这一点。请告知。
答案 0 :(得分:1)
对于#1,我将Collectors.groupingBy
与Collectors.counting
一起使用:
Map<String, Long> resourcesByCategoryCount = resources.stream()
.collect(Collectors.groupingBy(
Resource::getCategory,
Collectors.counting()));
这将Resource
元素按category
分组,计数其中有多少属于每个类别。
对于#2,我不会使用流。相反,我将使用Map.computeIfAbsent
操作(在Java 8中引入):
Map<String, Set<String>> distinctComponentsByCategory = new LinkedHashMap<>();
resources.forEach(r -> distinctComponentsByCategory.computeIfAbsent(
r.getCategory(),
k -> new HashSet<>())
.add(r.getGroup()));
这首先创建一个LinkedHashMap
(保留插入顺序)。然后,对Resource
元素进行迭代并将其放入此映射中,以使其按category
分组,并将每个group
添加到映射到每个HashSet
的位置类别。由于集合不允许重复,因此任何类别都不会有重复的组。然后,不同的组数就是每个组的大小。
对于#3,我将再次使用Collectors.groupingBy
和Collectors.counting
,但是我将使用复合键进行分组:
Map<List<String>, Long> resourcesByCategoryAndGroup = resources.stream()
.collect(Collectors.groupingBy(
r -> Arrays.asList(r.getCategory(), r.getGroup()), // or List.of
Collectors.counting()));
这将Resource
元素按category
和group
分组,计数每个(category, group)
对中有多少个元素。对于分组键,使用的是两个元素的List<String>
,其中category
是其第一元素,component
是其第二元素。
或者,您可以使用嵌套分组来代替使用组合键:
Map<String, Map<String, Long>> resourcesByCategoryAndGroup = resources.stream()
.collect(Collectors.groupingBy(
Resource::getCategory,
Collectors.groupingBy(
Resource::getGroup,
Collectors.counting())));
答案 1 :(得分:0)
感谢Fedrico的详细回复。 #1和#3表现出色。对于#2,我希望看到Map的输出。这是我目前正在使用的代码以获取该计数。这是不使用旧样式的收集器的。
HashMap<String, HashSet<String>> map = new HashMap<>();
for (Resource resource : resources) {
if (map.containsKey(resource.getCategory())) {
map.get(resource.getCategory()).add(resource.getGroup());
} else
HashSet<String> componentSet = new HashSet<>();
componentSet.add(resource.getGroup());
map.put(resource.getCategory(), componentSet);
}
}
log.info("Group count in each category");
for (Map.Entry<String, HashSet<String>> entry : map.entrySet()) {
log.info("{} - {}", entry.getKey(), entry.getValue().size());
}