Apart from the obvious solution of an utility method (already mentioned in my comment), I think the most straightforward idea to keep it OO is to implement your own Collector; Collector.of provides a straightforward way:
Collector collector = Collector.of(
() -> new HashMap<Record, Integer>(),
(result, record) -> {
// All of the filters and transformations in your chain.
// If the element is filtered out, exit doing nothing.
// If the element is not filtered out:
Integer total = result.get(transformedRecord);
if (total == null) {
total = 1;
} else {
total = total + 1;
}
result.put(transformedRecord, total);
},
(result1, result2) -> {
result1.addAll(result2);
return result1;
});
and
recordStream.collect(collector);
Of course, to reuse code you can create a factory/builder to provide the collection. Or you can even implement the Collector yourself with those functions.
In any case, remember that streams are not silver bullets. They are thought to make simple operations easy to write and read, but if using them gets complicated then you may find that they are not the right tool.