我有一个VO的arraylist。这些对象具有许多属性和相应的get / set方法。我想基于我将在运行时获得的属性对此数组列表进行排序。 让我详细解释一下。我的VO是这样的
I have an arraylist of VOs. These objects have many properties and corresponding get/set methods. I want to sort this array list based on a property which I'll be getting in runtime. Let me explain in detail. My VO is like this
public class Employee { String name; String id; private String getName() { return name; } private String getId() { return id; } }我将在运行时获取字符串'sortType' ,可以是'id'或'name'。我想根据字符串的值对列表进行排序。
I will be getting a string ‘sortType’ in runtime, which can be either ‘id’ or ‘name’. I want to sort the list based on the value of the string.
我试图一起使用比较器和反射,但没有运气。可能是我没有正确使用它。我不想使用if循环并创建新的比较器类。还有其他想法吗?
I have tried to use comparator and reflection together, but no luck. May be I didn't use it properly.I don’t want to use an if loop and create new comparator classes. Any other thoughts?
try catch应该在新类中。这是工作代码。如果你想为比较器使用一个单独的类,请在@ Bohemian的评论中找到它。
The try catch should be inside the new class. Here is the working code. If you want to use a separate class for comparator, please find it in @Bohemian's comment below.
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 s1pareTo(s2); } catch (Exception e) { return 0; } } });推荐答案
创建一个比较器用于工作:
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()pareTo(e2.getName()); } return e1.getId()pareTo(e2.getId()); } }然后使用它
String type = "name"; // determined at runtime Collections.sort(list, new EmployeeComparator(type));反射版本类似,除非您在获取对象上寻找方法+ type(大写)并调用它并将其强制转换为Comparable并使用compareTo(我将尝试显示代码,但我正在使用我的iPhone并且它有点延伸,但是这里去了)
The reflective version would be similar, except you would look for a method on the object of "get" + type (capitalised) and invoke that and hard cast it to Comparable and use compareTo (I'll try to show the code, but I'm using my iPhone and its a bit of a stretch, but here goes)
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 s1pareTo(s2); } }
好的......这是如何做到如果没有创建一个类,使用匿名类(异常处理所以代码编译):
OK... Here's how to do it without creating a class, using an anonymous class (with exception handling so code compiles):
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 s1pareTo(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); } } });