java 8 - What is the elegant way to generate Map from List using streams -
i have students list database. applied predicates list , partition list valid, invalid students. invalid students want generate map student key , error message value. because need generate report each student.here doing don't know whether approach or not or there better way it.
actually after getting invalid students list trying create function think code getting messy , may there better approach it. here doing
private list<predicate<olccstudent>> getallpredicates() { list<predicate<olccstudent>> allpredicates = arrays.aslist( isvalidfirstname(), isvalidmiddleinitial(), isvalidlastname(), isvalidstreetaddress(), isvalidcity(), isvalidstate(), isvalidzip(), isvaliddateofbirth(), isvalidssn(), isvalidtestdate(), isvalidtestanswers(), isvalidprovidercode(), isvalidinstructorcode() ); return allpredicates; } public map<boolean, list<olccstudent>> getstudentsmap(list<olccstudent> olccstudentslist) { list<predicate<olccstudent>> allpredicates = getallpredicates(); predicate<olccstudent> compositepredicate = allpredicates.stream() .reduce(w -> true, predicate::and); map<boolean, list<olccstudent>> studentsmap= olccstudentslist .stream() .collect(collectors.partitioningby(compositepredicate)); return studentsmap; } public map<olccstudent, string> getinvalidstudentsmap(map<boolean, list<olccstudent>> studentsmap) throws exception { list<olccstudent> invalidstudentslist = studentsmap.entryset() .stream() .filter(p -> p.getkey() == boolean.false) .flatmap(p -> p.getvalue().stream()) .collect(collectors.tolist()); function<list<olccstudent>, map<olccstudent, string>> invalidstudentfunction = list -> { map<olccstudent, string> invalidstudentsmap = new linkedhashmap<>(); list.foreach(student-> { string errormessage = getstudenterrormessage(student); invalidstudentsmap.put(student, errormessage); }); return invalidstudentsmap; }; map<olccstudent, string> invalidstudentsmap = invalidstudentfunction.apply(invalidstudentslist); return invalidstudentsmap; return null; } private string getstudenterrormessage(olccstudent student) { string firstname = student.getfirstname(); string middleinitial = student.getmiddleinitial(); string lastname = student.getlastname(); string streetaddress = student.getstreetaddress(); .... stringbuilder errorbuilder = new stringbuilder(); //the predicate 'negate' method returns predicate represents logical negation or opposite if (isvalidfirstname().negate().test(student)) { string error = "invalid firstname: " + firstname; errorbuilder.append(error + error_message_seperator); } if (isvalidmiddleinitial().negate().test(student)) { string error = "invalid middle initial: " + middleinitial; errorbuilder.append(error + error_message_seperator); } if (isvalidlastname().negate().test(student)) { string error = "invalid lastname: " + lastname; errorbuilder.append(error + error_message_seperator); } if (isvalidstreetaddress().negate().test(student)) { string error = "invalid streetaddress: " + streetaddress; errorbuilder.append(error + error_message_seperator); } ... if (errorbuilder.length() > 0) { errorbuilder.deletecharat(errorbuilder.length() - 1); } return errorbuilder.tostring().trim(); }
actually confuse getstudenterrormessage()
calling list.foreach()
. know collectors provide collectors.joining
function. want in predicate manner. created list of predicates , use in streams. can similar thing error messages? create stream invalid students list
, , using collectors.tomap()
, put student key , error message value.
thanks
edit ----------------
public class olccstudentpredicate { public static predicate<olccstudent> isvalidtestdate() { return p -> isvaliddate(p.gettestdate()); } public static predicate<olccstudent> isvaliddateofbirth() { return p -> isvaliddate(p.getdateofbirth()); } ... private static boolean isvaliddate(string date) { boolean valid = false; if (stringutils.isnotblank(date)) { try { localdate.parse(date, datetimeformatter.ofpattern("mm/dd/yyyy")); valid = true; } catch (datetimeparseexception e) { } } return valid; } @test public void test() { list<olccstudent> olccstudentslist = getolccstudentslist(); try { map<olccstudent, string> map = getinvalidstudentsmap(olccstudentslist); system.out.println(); //olccstudentservice.getstudentsmap(olccstudentslist); } catch (exception e) { e.printstacktrace(); } } private list<olccstudent> getolccstudentslist() { list<olccstudent> olccstudentslist = new arraylist<>(); olccstudent student1 = new olccstudent(1l, 1l, "firstname1", "middleinitial1", "lastname1", "email1", "streetadress1", "city1", "state1", "1234", "01/22/2015", "phonenumber1", "01/22/2015", "123456789", "testform1", "providercode1", "instructorcode1", "surveyanswer1", "testidentifier1", "testanswers1"); olccstudent student2 = new olccstudent(2l, 2l, "firstname2", "middleinitial2", "lastname2", "email2", "streetadress2", "city2", "state2", "5678", "02/22/2015", "phonenumber2", "02/22/2015", "987654321", "testform2", "providercode2", "instructorcode2", "surveyanswer2", "testidentifier2", "testanswers2"); olccstudent student3 = new olccstudent(3l,3l, "firstname3", "middleinitial3", "lastname3", "email3", "streetadress3", "city3", "state3", "zip3", "testdate3", "phonenumber3", "dateofbirth3", "socialsecuritynumber3", "testform3", "providercode3", "instructorcode3", "surveyanswer3", "testidentifier3", "testanswers3"); olccstudent student4 = new olccstudent(4l, 4l, "firstname4", "middleinitial4", "lastname4", "email4", "streetadress4", "city4", "state4", "zip4", "testdate4", "phonenumber4", "dateofbirth4", "socialsecuritynumber4", "testform4", "providercode4", "instructorcode4", "surveyanswer4", "testidentifier4", "testanswers4"); olccstudentslist.add(student1); olccstudentslist.add(student2); olccstudentslist.add(student3); olccstudentslist.add(student4); return olccstudentslist; } private string validate(olccstudent student) { string firstname = student.getfirstname(); string middleinitial = student.getmiddleinitial(); string lastname = student.getlastname(); string streetaddress = student.getstreetaddress(); string city = student.getcity(); string state = student.getstate(); string zip = student.getzip(); string dateofbirth = student.getdateofbirth(); string ssn = student.getsocialsecuritynumber(); string phonenumber = student.getphonenumber(); string testdate = student.gettestdate(); string testform = student.gettestform(); string testanswers = student.gettestanswers(); string providercode = student.getprovidercode(); string instructorcode = student.getinstructorcode(); stringbuilder errorbuilder = new stringbuilder(); //the predicate 'negate' method returns predicate represents logical negation or opposite if (isvalidfirstname().negate().test(student)) { string error = "invalid firstname: " + firstname; errorbuilder.append(error + error_message_seperator); } if (isvalidmiddleinitial().negate().test(student)) { string error = "invalid middle initial: " + middleinitial; errorbuilder.append(error + error_message_seperator); } if (isvalidlastname().negate().test(student)) { string error = "invalid lastname: " + lastname; errorbuilder.append(error + error_message_seperator); } if (isvalidstreetaddress().negate().test(student)) { string error = "invalid streetaddress: " + streetaddress; errorbuilder.append(error + error_message_seperator); } if (isvalidcity().negate().test(student)) { string error = "invalid city: " + city; errorbuilder.append(error + error_message_seperator); } if (isvalidstate().negate().test(student)) { string error = "invalid state: " + state; errorbuilder.append(error + error_message_seperator); } if (isvalidzip().negate().test(student)) { string error = "invalid zip: " + zip; errorbuilder.append(error + error_message_seperator); } if (isvaliddateofbirth().negate().test(student)) { string error = "invalid dateofbirth: " + dateofbirth; errorbuilder.append(error + error_message_seperator); } if (isvalidssn().negate().test(student)) { string error = "invalid ssn: " + ssn; errorbuilder.append(error + error_message_seperator); } if (isvalidtestdate().negate().test(student)) { string error = "invalid testdate: " + testdate; errorbuilder.append(error + error_message_seperator); } if (isvalidtestanswers().negate().test(student)) { string error = "invalid testanswers: " + testanswers; errorbuilder.append(error + error_message_seperator); } if (isvalidprovidercode().negate().test(student)) { string error = "invalid providecode: " + providercode; errorbuilder.append(error + error_message_seperator); } if (isvalidinstructorcode().negate().test(student)) { string error = "invalid instructorcode: " + instructorcode; errorbuilder.append(error + error_message_seperator); } if (errorbuilder.length() > 0) { errorbuilder.deletecharat(errorbuilder.length() - 1); } return errorbuilder.tostring().trim(); } public map<olccstudent, string> getinvalidstudentsmap(list<olccstudent> studentslist) throws exception { map<olccstudent, string> map = studentslist.stream() // step 1: validate each student, keeping track of error message generated. .collect(collectors.tomap(function.identity(), student -> validate(student))) // step 2: keep have error message associated. .entryset() .stream() .filter(entry -> entry.getvalue() != null) // step 3: generate map. .collect(collectors.tomap(entry -> entry.getkey(), entry -> entry.getvalue())); return map; }
i create validationrule
class stick validation predicate , error message formatter:
static class validationrule { public final predicate<olccstudent> predicate; public final function<olccstudent, string> errorformatter; public validationrule(predicate<olccstudent> predicate, function<olccstudent, string> errorformatter) { this.predicate = predicate; this.errorformatter = errorformatter; } }
now getallrules
this:
public static list<validationrule> getallrules() { return arrays.aslist( new validationrule(isvalidfirstname(), s -> "invalid firstname: " + s.getfirstname()), new validationrule(isvalidmiddleinitial(), s -> "invalid middle initial: " + s.getmiddleinitial()), new validationrule(isvalidlastname(), s -> "invalid lastname: " + s.getlastname()), new validationrule(isvalidstreetaddress(), s -> "invalid streetaddress: " + s.getstreetaddress()) // ... ); }
and can map of invalid students in following way:
public map<olccstudent, string> getinvalidstudentsmap(list<olccstudent> students) { list<validationrule> rules = getallrules(); return students .stream() .<entry<olccstudent, string>>map(student -> new abstractmap.simpleentry<>(student, rules .stream() .filter(rule -> rule.predicate.test(student)) .map(rule -> rule.errorformatter.apply(student)) .collect(collectors.joining(error_message_seperator)))) .filter(entry -> !entry.getvalue().isempty()) .collect(collectors.tomap(entry -> entry.getkey(), entry -> entry.getvalue())); }
Comments
Post a Comment