java - Reusing part of Stream mapping and filtering to compose two different results -
i'd know if there way of reusing common stream operation varies in end different outputs. example bellow i'm trying compact one-step operation:
public static departmentinfo extractdepartmentinfo(baselinepolicy resource) throws resourceprocessorerror { function<exception, exception> rpe = e -> new resourceprocessorerror(e.getmessage()); list<string> parents = objects.requirenonnull( exceptions.trying( () -> arrays.aslist(exceptions.dangerous(resource::getparentids).expecting(cmexception.class).throwing(rpe)) .stream() .map(cid -> exceptions.dangerous(cid, resource.getcmserver()::getpolicy).expecting(cmexception.class).throwing(rpe)) .filter(policy -> pagepolicy.class.isassignablefrom(policy.getclass())) .map(pagepolicy.class::cast) .filter(page -> exceptions.dangerous(page, p -> boolean.valueof(p.getcomponentnotnull(componentconstants.polopoly_client, componentconstants.is_home_department, boolean.false.tostring())).booleanvalue()) .expecting(cmexception.class).throwing(rpe)) .map(page -> exceptions.dangerous(page, p -> p.getexternalid().getexternalid()).expecting(cmexception.class).throwing(rpe)), resourceprocessorerror.class) .collect(collectors.tolist())); string externalid = parents.get(parents.size()-1).tostring(); list<string> list = objects.requirenonnull( exceptions.trying( () -> arrays.aslist(exceptions.dangerous(resource::getparentids).expecting(cmexception.class).throwing(rpe)) .stream() .map(cid -> exceptions.dangerous(cid, resource.getcmserver()::getpolicy).expecting(cmexception.class).throwing(rpe)) .filter(policy -> pagepolicy.class.isassignablefrom(policy.getclass())) .map(pagepolicy.class::cast) .map(page -> exceptions.dangerous(page, p -> p.getchildpolicy(path_segment) != null && stringutils.haslength(singlevalued.class.cast(p.getchildpolicy(path_segment)).getvalue())? singlevalued.class.cast(p.getchildpolicy(path_segment)).getvalue(): p.getname()).expecting(cmexception.class).throwing(rpe)) .filter(val -> val != null && !val.isempty()), resourceprocessorerror.class) .collect(collectors.tolist())); if(list.size() > 3) { list = list.sublist(list.size() - 3, list.size()-1); } switch(list.size()) { case 0: { throw new resourceprocessorerror("br.com.oesp.xmlrender.error.noproduct"); } case 1: { return departmentinfo.withproduct(list.get(0), externalid); } case 2: { return departmentinfo.withproduct(list.get(0), externalid).withdepartment(list.get(1)); } default: { return departmentinfo.withproduct(list.get(0), externalid).withdepartment(list.get(1)).withsubdepartment(list.get(2)); } } }
notice first step repeated both:
list<string> parents = objects.requirenonnull( exceptions.trying( () -> arrays.aslist(exceptions.dangerous(resource::getparentids).expecting(cmexception.class).throwing(rpe)) .stream() .map(cid -> exceptions.dangerous(cid, resource.getcmserver()::getpolicy).expecting(cmexception.class).throwing(rpe)) .filter(policy -> pagepolicy.class.isassignablefrom(policy.getclass())) .map(pagepolicy.class::cast)
it's not problem reading specially because i'm redoing heavy operation twice, meanwhile in more imperative way i'd once.
there 2 things you're trying do:
- avoid redundant work of creating input array
- avoid redundant code of map/filter/map
the first easy:
list<id> list = arrays.aslist(exceptions.dangerous(resource::getparentids) .expecting(cmexception.class) .throwing(rpe));
now can pull streams source twice without rematerializing it.
the next bit function list stream:
function<list<id>, stream<something>> asstream = list -> list.stream().map(...).filter(...).map(...);
now, start stream this:
asstream.apply(list).morestuff().morestuff()
Comments
Post a Comment