根据运行时属性对对象列表进行排序

我有一个VO的arraylist。 这些对象具有许多属性和相应的get / set方法。 我想基于我将在运行时获得的属性对此数组列表进行排序。 让我详细解释一下。 我的VO是这样的

public class Employee { String name; String id; private String getName() { return name; } private String getId() { return id; } } 

我将在运行时获得一个字符串’sortType’,它可以是’id’或’name’。 我想根据字符串的值对列表进行排序。

我试图一起使用比较器和reflection,但没有运气。 可能是我没有正确使用它。我不想使用if循环并创建新的比较器类。 还有其他想法吗?

try catch应该在新类中。 这是工作代码。 如果你想为比较器使用一个单独的类,请在@ Bohemian的评论中找到它。

  String sortType = "name"; // determined at runtime Collections.sort(results, new Comparator() { 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 { 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)); 

reflection版本会类似,除非你在“get”+类型(大写)对象上寻找一个方法并调用它并将其强制转换为Comparable并使用compareTo(我将尝试显示代码,但我我正在使用我的iPhone而且有点长,但是这里有

 public class DynamicComparator implements Comparator { 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); } } 

OK …以下是如何在创建类的情况下使用匿名类(具有exception处理以便代码编译):

 List list; final String attribute = "Name"; // for example. Also, this is case-sensitive Collections.sort(list, new Comparator() { 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); } } }); 

请执行下列操作:

  • 从客户端获取字段的名称
  • 构建getter的名称 – >“get”+字段名称(大写第一个字符后)
  • 尝试使用Class.getDeclaredMethod()查找带reflection的方法
  • 如果找到,则在VO类的两个实例上调用返回的Method对象
  • 使用调用的getter方法的结果进行排序

把事情简单化!

如果选择只是idname -use if语句。

在两个选择之间挑选。 这就是如果被发明的话。

或者,如果它是许多属性,则使用reflection,或者首先将数据存储在Map中。 有时Map比一个类更好。 特别是如果你的VO没有getter和setter以外的方法。

但是请注意,在这种情况下使用reflection可能是不安全的,因为您的客户端可能会在类似于SQL注入的攻击中注入CGI参数中的任何术语。