我的数组列表为Value Objects [VO]。这些对象具有许多属性和相应的获取/设置方法。我想基于将在运行时获取的属性对该数组列表进行排序。让我详细解释。我的VO是这样的
public class Employee {
String name;
String id;
private String getName() {
return name;
}
private String getId() {
return id;
}
}
我将在运行时获取字符串sortType
,可以是"id"
或"name"
。我想根据字符串的值对列表进行排序。
我试图同时使用比较器和反射,但是没有运气。可能是我没有正确使用它。我不想使用if循环并创建新的比较器类。还有其他想法吗?
try catch应该在新类中。这是工作代码。如果要为比较器使用单独的类,请在下面的@Bohemian注释中找到它。
String sortType = "name"; // determined at runtime
Collections.sort(results, new Comparator<Employee>() {
public int compare(Employee c1, Employee c2) {
try{
Method m = c1.getClass().getMethod("get" + StringUtils.capitalize(sortType));
String s1 = (String)m.invoke(c1);
String s2 = (String)m.invoke(c2);
return s1.compareTo(s2);
}
catch (Exception e) {
return 0;
}
}
});
为作业创建Comparator
:
public class EmployeeComparator implements Comparator<Employee> {
private final String type;
public EmployeeComparator (String type) {
this.type = type;
}
public int compare(Employee e1, Employee e2) {
if (type.equals("name")) {
return e1.getName().compareTo(e2.getName());
}
return e1.getId().compareTo(e2.getId());
}
}
然后使用它
String type = "name"; // determined at runtime
Collections.sort(list, new EmployeeComparator(type));
反射版本将是相似的,除了您会在“获取” +类型(大写)的对象上寻找一个方法,然后调用该方法并将其强制转换为Comparable并使用compareTo(我将尝试显示代码,但我正在使用我的iPhone及其一些功能,但是可以使用)
public class DynamicComparator implements Comparator<Object> {
private final String type;
// pass in type capitalised, eg "Name"
// ie the getter method name minus the "get"
public DynamicComparator (String type) {
this.type = type;
}
public int compare(Object o1, Object o2) {
// try-catch omitted
Method m = o1.getClass().getMethod("get" + type);
String s1 = (String)m.invoke(o1);
String s2 = (String)m.invoke(o2);
return s1.compareTo(s2);
}
}
确定...这是操作方法无使用匿名类创建类(具有异常处理,以便代码编译):
List<?> list;
final String attribute = "Name"; // for example. Also, this is case-sensitive
Collections.sort(list, new Comparator<Object>() {
public int compare(Object o1, Object o2) {
try {
Method m = o1.getClass().getMethod("get" + attribute);
// Assume String type. If different, you must handle each type
String s1 = (String) m.invoke(o1);
String s2 = (String) m.invoke(o2);
return s1.compareTo(s2);
// simply re-throw checked exceptions wrapped in an unchecked exception
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
});
执行以下操作:
如果选择仅是id
或name
,请使用if语句。
在两个选择之间选择。这就是发明的目的。
或者,如果有很多属性,则使用反射,或首先将数据存储在Map
中。有时Map
比一门课好。特别是如果您的VO除了getter和setter之外没有其他方法。
但是请注意,在这种情况下使用反射可能是不安全的,因为您的客户端可能会在类似于SQL注入的攻击中注入CGI参数中的任何术语。