java - Passing Object type and Field to Comparator -
is possible write comparator
can pass object type, field type , field sort on? i've made small changes http://www.davekoelle.com/files/alphanumcomparator.java accommodate sorting on field email
of type string
in object type user
. have code works.
public class main { public static void main(string[] args) { list<user> users = new arraylist<>(); users.add(new user(7, "user1", "user1@c.com")); users.add(new user(11, "user20", "user20@c.com")); users.add(new user(5, "admin20", "admin20@c.com")); users.add(new user(10, "user11", "user11@c.com")); users.add(new user(6, "admin21", "admin21@c.com")); users.add(new user(12, "user21", "user21@c.com")); users.add(new user(8, "user2", "user2@c.com")); users.add(new user(1, "admin1", "admin1@c.com")); users.add(new user(3, "admin10", "admin10@c.com")); users.add(new user(2, "admin2", "admin2@c.com")); users.add(new user(9, "user10", "user10@c.com")); users.add(new user(4, "admin11", "admin11@c.com")); (user item : users) { system.out.println(item.getemail()); } system.out.println("__________________________"); collections.sort(users, new alphanumcomparator()); (user item : users) { system.out.println(item.getemail()); } } }
.
public class user { int id; string name; string email; // constructor, getters , setters }
.
public class alphanumcomparator implements comparator<user> { private final boolean isdigit(char ch) { return ((ch >= 48) && (ch <= 57)); } /** * length of string passed in improved efficiency (only need calculate once) **/ private final string getchunk(string s, int slength, int marker) { stringbuilder chunk = new stringbuilder(); char c = s.charat(marker); chunk.append(c); marker++; if (isdigit(c)) { while (marker < slength) { c = s.charat(marker); if (!isdigit(c)) break; chunk.append(c); marker++; } } else { while (marker < slength) { c = s.charat(marker); if (isdigit(c)) break; chunk.append(c); marker++; } } return chunk.tostring(); } public int compare(user u1, user u2) { if ((u1 == null) || (u2 == null)) { return 0; } int thismarker = 0; int thatmarker = 0; int s1length = u1.getemail().length(); int s2length = u2.getemail().length(); while (thismarker < s1length && thatmarker < s2length) { string thischunk = getchunk(u1.getemail(), s1length, thismarker); thismarker += thischunk.length(); string thatchunk = getchunk(u2.getemail(), s2length, thatmarker); thatmarker += thatchunk.length(); // if both chunks contain numeric characters, sort them numerically int result = 0; if (isdigit(thischunk.charat(0)) && isdigit(thatchunk.charat(0))) { // simple chunk comparison length. int thischunklength = thischunk.length(); result = thischunklength - thatchunk.length(); // if equal, first different number counts if (result == 0) { (int = 0; < thischunklength; i++) { result = thischunk.charat(i) - thatchunk.charat(i); if (result != 0) { return result; } } } } else { result = thischunk.compareto(thatchunk); } if (result != 0) return result; } return s1length - s2length; } }
how can pass object type, field type , field sort on collections.sort(users, new alphanumcomparator());
in main
class alphanumcomparator
, how can accommodate in alphanumcomparator
? in case pass object type user
field email
, field type string
. if sort on id
pass object type user
, field email
, field type int
.
i keep alphanumcomparator is, , create new class fieldcomparator:
public class fieldcomparator<t> implements comparator<t> { private static final logger log = logger.getlogger( fieldcomparator.class.getname()); private static final alphanumcomparator alphanum = new alphanumcomparator(); private final field field; private final boolean isstring; private final boolean iscomparable; public fieldcomparator(class<t> clazz, string name) { try { field = clazz.getdeclaredfield(name); field.setaccessible(true); class<?> fieldtype = field.gettype(); isstring = fieldtype == string.class; iscomparable = comparable.class.isassignablefrom(fieldtype); } catch (nosuchfieldexception | securityexception ex) { log.log(level.severe, null, ex); throw new runtimeexception(ex.getmessage()); } } @override public int compare(t o1, t o2) { try { object value1 = field.get(o1); object value2 = field.get(o2); if (value1 == null) { return value2 == null ? 0 : -1; } else if (value2 == null) { return 1; } else if (isstring) { return alphanum.compare((string)value1, (string)value2); } else if (iscomparable) { return ((comparable)value1).compareto(value2); } else { // don't know how compare fields return 0; } } catch (illegalargumentexception | illegalaccessexception ex) { log.log(level.severe, null, ex); throw new runtimeexception(ex.getmessage()); } } }
update:
to deal primitive types, can change 1 line of method compare:
} else if (iscomparable || value1 instanceof comparable) {
update 2:
you main method become:
public static void main(string[] args) { list<user> users = new arraylist<>(); users.add(new user(7, "user1", "user1@c.com")); users.add(new user(11, "user20", "user20@c.com")); users.add(new user(5, "admin20", "admin20@c.com")); users.add(new user(10, "user11", "user11@c.com")); users.add(new user(6, "admin21", "admin21@c.com")); users.add(new user(12, "user21", "user21@c.com")); users.add(new user(8, "user2", "user2@c.com")); users.add(new user(1, "admin1", "admin1@c.com")); users.add(new user(3, "admin10", "admin10@c.com")); users.add(new user(2, "admin2", "admin2@c.com")); users.add(new user(9, "user10", "user10@c.com")); users.add(new user(4, "admin11", "admin11@c.com")); (user item : users) { system.out.println(item.getemail()); } system.out.println("__________________________"); collections.sort(users, new fieldcomparator(user.class, "email")); (user item : users) { system.out.println(item.getemail()); } system.out.println("__________________________"); collections.sort(users, new fieldcomparator(user.class, "name")); (user item : users) { system.out.println(item.getemail()); } system.out.println("__________________________"); collections.sort(users, new fieldcomparator(user.class, "id")); (user item : users) { system.out.println(item.getemail()); } }
Comments
Post a Comment