Для # 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
(который сохраняет порядок вставки * 1024). *). Затем элементы 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())));