是否可以编写Comparator
以便我可以传递Object类型,字段类型和我想要排序的字段?我对http://www.davekoelle.com/files/AlphanumComparator.java进行了一些小的更改,以便在对象类型email
中对String
类型的字段User
进行排序。我有这个代码可行。
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"));
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<User> {
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());
类Main
中的对象类型,字段类型和我想要排序的字段传递给AlphanumComparator
,我如何在{ {1}}?所以在这种情况下,我会传递对象类型AlphanumComparator
字段User
和字段类型email
。但如果我想对String
进行排序,我会传递对象类型id
,字段User
和字段类型email
。
答案 0 :(得分:1)
我会按原样保留AlphanumComparator,并创建一个新类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 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<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"));
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());
}
}