将对象类型和字段传递给比较器

是否可以编写一个Comparator以便我可以传递Object类型,字段类型和我想要排序的字段? 我对http://www.davekoelle.com/files/AlphanumComparator.java进行了一些小的更改,以适应对象类型User String类型的字段email的排序。 我有这个代码有效。

 public class Main { public static void main(String[] args) { List 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")); for (User item : users) { System.out.println(item.getEmail()); } System.out.println("__________________________"); Collections.sort(users, new AlphanumComparator()); for (User item : users) { System.out.println(item.getEmail()); } } } 

 public class User { int id; String name; String email; // Constructor, Getters and Setters } 

 public class AlphanumComparator implements Comparator { private final boolean isDigit(char ch) { return ((ch >= 48) && (ch <= 57)); } /** * Length of string is passed in for improved efficiency (only need to calculate it 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 by length. int thisChunkLength = thisChunk.length(); result = thisChunkLength - thatChunk.length(); // If equal, the first different number counts if (result == 0) { for (int i = 0; i < 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; } } 

如何从Collections.sort(users, new AlphanumComparator());传递对象类型,字段类型和我想要排序的字段Collections.sort(users, new AlphanumComparator());AlphanumComparatorMain类中,我如何在AlphanumComparator容纳这个? 所以在这种情况下,我会传递对象类型User字段email和字段类型String 。 但是如果我喜欢对id进行排序,我会传递对象类型User ,field email和field type int

我会按原样保留AlphanumComparator,并创建一个新类FieldComparator:

 public class FieldComparator implements Comparator { 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 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 to compare fields return 0; } } catch (IllegalArgumentException | IllegalAccessException ex) { LOG.log(Level.SEVERE, null, ex); throw new RuntimeException(ex.getMessage()); } } } 

更新:

要处理原始类型,可以更改一行方法比较:

  } else if (isComparable || value1 instanceof Comparable) { 

更新2:

你的主要方法将成为:

 public static void main(String[] args) { List 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")); for (User item : users) { System.out.println(item.getEmail()); } System.out.println("__________________________"); Collections.sort(users, new FieldComparator(User.class, "email")); for (User item : users) { System.out.println(item.getEmail()); } System.out.println("__________________________"); Collections.sort(users, new FieldComparator(User.class, "name")); for (User item : users) { System.out.println(item.getEmail()); } System.out.println("__________________________"); Collections.sort(users, new FieldComparator(User.class, "id")); for (User item : users) { System.out.println(item.getEmail()); } }