java - Library function to do bean comparison using Functions? -


since java 8 has made easier ever refer method directly (function/lambda), traditional reflection-based bean comparators (e.g. common-lang's equalsbuilder) can implemented cleanly without reflection. wondering available in well-known library already?

just clear, after function similar signature:

static <t> boolean equals(t a, t b, function<t, ?>... proprefs); 

alternatively, non-confusion way of implementing using streams?

given example class like

class person {     long id;     string name, surname;     int age;      public long getid() {         return id;     }     public string getname() {         return name;     }     public string getsurname() {         return surname;     }     public int getage() {         return age;     } } 

of course, can in compact form like

@override public boolean equals(object obj) {     if(obj==this) return true;     if(!(obj instanceof person)) return false;     person p=(person)obj;     return stream.<function<person,?>>of(           person::getname, person::getsurname, person::getage)       .allmatch(f->objects.equals(f.apply(this), f.apply(p))); } 

but raises big question whether win compared simple form

@override public boolean equals(object obj) {     if(obj==this) return true;     if(!(obj instanceof person)) return false;     person p=(person)obj;     return this.age==p.age && objects.equals(this.name, p.name)       && objects.equals(this.surname, p.surname); } 

as doesn’t add brevity of code , can’t prevent neither, forgetting significant property nor mismatches between equals implementation , hashcode implementation.

note applies equalsbuilder; it’s not helping regarding critical issues (actually, can’t see any advantage).

if want gain advantage out of it, have resort not-so compact implementation:

static list<function<person,?>> eq_props=arrays.aslist(     person::getname, person::getsurname, person::getage);  @override public boolean equals(object obj) {     if(obj==this) return true;     if(!(obj instanceof person)) return false;     person p=(person)obj;     return eq_props.stream().allmatch(f->objects.equals(f.apply(this), f.apply(p))); } @override public int hashcode() {     return objects.hash(eq_props.stream().map(f->f.apply(this)).toarray()); } 

we still can’t guaranty there no relevant property missing, @ least have single point of responsibility need check , have ensured equality , hash code consistent, there one advantage on manual implementation.

if worry performance implication of temporary objects, may combine functions actual operation can performed without temporary object:

static list<function<person,?>> eq_props=arrays.aslist(     person::getname, person::getsurname, person::getage);  static bipredicate<person,person> equal=eq_props.stream()     .<bipredicate<person,person>>map(f -> (a,b) -> objects.equals(f.apply(a), f.apply(b)))     .reduce(bipredicate::and).get();  static tointfunction<person> hash=eq_props.stream()     .<tointfunction<person>>map(f -> -> objects.hash(f.apply(a)))     .reduce((f,g) -> x -> f.applyasint(x)*31+g.applyasint(x)).get();  @override public boolean equals(object obj) {     return obj==this || (obj instanceof person)&& equal.test(this, (person)obj); } @override public int hashcode() {     return hash.applyasint(this); } 

Comments

Popular posts from this blog

javascript - AngularJS custom datepicker directive -

javascript - jQuery date picker - Disable dates after the selection from the first date picker -