Вы можете реализовать пользовательский сборщик , см. Пример в этой статье :
public class Scratch {
public static final String FIRST_ID = "firstId";
public static final String SECOND_ID = "secondId";
private static class AnObjectFieldCounter implements Collector<AnObject, Map<String, Map<Long, Long>>, Map<String, Map<Long, Long>>> {
@Override
public Supplier<Map<String, Map<Long, Long>>> supplier() {
return HashMap::new;
}
@Override
public BiConsumer<Map<String, Map<Long, Long>>, AnObject> accumulator() {
return (map, obj) -> {
Map<Long, Long> inner;
inner = map.getOrDefault(FIRST_ID, new HashMap<>());
inner.compute(obj.getFirstId(), (id, count) -> (count == null) ? 1 : count + 1);
map.put(FIRST_ID, inner);
inner = map.getOrDefault(SECOND_ID, new HashMap<>());
inner.compute(obj.getSecondId(), (id, count) -> (count == null) ? 1 : count + 1);
map.put(SECOND_ID, inner);
};
}
@Override
public BinaryOperator<Map<String, Map<Long, Long>>> combiner() {
return (a, b) -> {
Map<Long, Long> firstIdCountMap = Stream
.concat(a.get(FIRST_ID).entrySet().stream(), b.get(FIRST_ID).entrySet().stream())
.collect(groupingBy(Map.Entry::getKey, Collectors.summingLong(Map.Entry::getValue)));
Map<Long, Long> secondIdCountMap = Stream
.concat(a.get(SECOND_ID).entrySet().stream(), b.get(SECOND_ID).entrySet().stream())
.collect(groupingBy(Map.Entry::getKey, Collectors.summingLong(Map.Entry::getValue)));
Map<String, Map<Long, Long>> result = new HashMap<>();
result.put(FIRST_ID, firstIdCountMap);
result.put(SECOND_ID, secondIdCountMap);
return result;
};
}
@Override
public Function<Map<String, Map<Long, Long>>, Map<String, Map<Long, Long>>> finisher() {
return Function.identity();
}
@Override
public Set<Characteristics> characteristics() {
return new HashSet<>(Arrays.asList(UNORDERED, IDENTITY_FINISH));
}
}
public static void main(String[] args) {
List<AnObject> objects = createObjects();
Map<String, Map<Long, Long>> countedWithCollector = countUsingCollector(objects);
Map<String, Map<Long, Long>> countedWithStream = countUsingStream(objects);
Map<String, Map<Long, Long>> countedWithFor = countUsingFor(objects);
}
private static Map<String, Map<Long, Long>> countUsingCollector(List<AnObject> objects) {
Map<String, Map<Long, Long>> result = objects.stream().collect(new AnObjectFieldCounter());
return ImmutableMap.<String, Map<Long, Long>>builder().putAll(result).build();
}
//...
}