I have a set of domain objects that inherit from a shared type (i.e. GroupRecord extends Record
, RequestRecord extends Record
). The subtypes have specific properties (i.e. GroupRecord::getCumulativeTime
, RequestRecord::getResponseTime
).
Further, I have a list of records with mixed subtypes as a result of parsing a logfile.
List<Record> records = parseLog(...);
In order to compute statistics on the log records, I want to apply math functions only on a subset of the records that matches a specific subtype, i.e. only on GroupRecord
s. Therefore I want to have a filtered stream of specific subtypes. I know that I can apply a filter
and map
to a subtype using
records.stream()
.filter(GroupRecord.class::isInstance)
.map(GroupRecord.class::cast)
.collect(...
Apply this filter&cast on the stream multiple times (especially when doing it for the same subtype multiple times for different computations) is not only cumbersome but produces lots of duplication.
My current approach is to use a TypeFilter
class TypeFilter<T>{
private final Class<T> type;
public TypeFilter(final Class<T> type) {
this.type = type;
}
public Stream<T> filter(Stream<?> inStream) {
return inStream.filter(type::isInstance).map(type::cast);
}
}
To be applied to a stream:
TypeFilter<GroupRecord> groupFilter = new TypeFilter(GroupRecord.class);
SomeStatsResult stats1 = groupFilter.filter(records.stream())
.collect(...)
SomeStatsResult stats2 = groupFilter.filter(records.stream())
.collect(...)
It works, but I find this approach a bit much for such a simple task. Therefore I wonder, is there a better or what is the best way for making this behavior reusable using streams and functions in a concise and readable way?