这已被问了一千次,但我看到的所有答案都不适用于传递的对象,它们总是硬编码到哪个对象和哪个字段。我正在寻找一种基于字符串字段对List / Vector进行排序的方法。我不介意它是否使用Reflection或Voodoo魔法。
我写的方法导致 StackOverFlowError (双关语!)。
我按如下方式调用我的方法:
StandardComparator.sort("distance",Vector<?>)StaticItems.LocationList,Item.SingleLocation.class);
StandardComparator类定义如下:
public class StandardComparator {
public static void sort(final String field, Vector<?> locationList, final Class typeOfObject){
Collections.sort(locationList, new Comparator<Object>() {
@Override
public int compare(Object object1, Object object2) {
try {
return this.compare(typeOfObject.getField(field),typeOfObject.getField(field));
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return 0;
}
});
}
}
错误:
E/AndroidRuntime(22828): FATAL EXCEPTION: Thread-10
E/AndroidRuntime(22828): java.lang.StackOverflowError
E/AndroidRuntime(22828): at java.lang.reflect.Field.<init>(Field.java:89)
E/AndroidRuntime(22828): at java.lang.reflect.Field.<init>(Field.java:81)
E/AndroidRuntime(22828): at java.lang.reflect.ReflectionAccessImpl.clone(ReflectionAccessImpl.java:42)
E/AndroidRuntime(22828): at java.lang.Class.getField(Class.java:870)
E/AndroidRuntime(22828): at com.AtClass.Extras.StandardComparator$1.compare(StandardComparator.java:24)
SingleLocation对象:
public class SingleLocation {
int id;
public String deviceId;
public String title;
public String message;
public double latCoords;
public double lngCoords;
public String locSeen;
public Bitmap icon;
public double distance;
public String distanceString;
public SingleLocation(String id, String deviceId, String title, String message, String latCoords, String lngCoords, String locSeen){
this.id = Integer.valueOf(id);
this.deviceId = deviceId;
this.title = title;
this.message = message;
this.latCoords = Double.valueOf(latCoords);
this.lngCoords = Double.valueOf(lngCoords);
this.locSeen = locSeen;
}
}
答案 0 :(得分:1)
您只是调用自己的方法,导致堆栈溢出。由于您知道字段为String
,因此只需将其转换为String
并使用其compareTo()
方法即可。
答案 1 :(得分:1)
这是一个适用于任何Comparable字段的示例。您必须为基本类型和不可比较的数据添加特殊处理:
import java.lang.reflect.Field;
import java.util.*;
public class ReflectionBasedComparator {
public static void main(String[] args) {
List<Foo> foos = Arrays.asList(new Foo("a", "z"), new Foo("z", "a"), new Foo("n", "n"));
Collections.sort(foos, new ReflectiveComparator("s"));
System.out.println(foos);
Collections.sort(foos, new ReflectiveComparator("t"));
System.out.println(foos);
}
static class Foo {
private String s;
private String t;
public Foo(String s, String t) {
this.s = s;
this.t = t;
}
@Override
public String toString() {
return "Foo{" +
"s='" + s + '\'' +
", t='" + t + '\'' +
'}';
}
}
private static class ReflectiveComparator implements Comparator<Object> {
private String fieldName;
public ReflectiveComparator(String fieldName) {
this.fieldName = fieldName;
}
@Override
public int compare(Object o1, Object o2) {
try {
Field field = o1.getClass().getDeclaredField(fieldName);
if (!Comparable.class.isAssignableFrom(field.getType())) {
System.out.println(field.getType());
throw new IllegalStateException("Field not Comparable: " + field);
}
field.setAccessible(true);
Comparable o1FieldValue = (Comparable) field.get(o1);
Comparable o2FieldValue = (Comparable) field.get(o2);
return o1FieldValue.compareTo(o2FieldValue);
} catch (NoSuchFieldException e) {
throw new IllegalStateException("Field doesn't exist", e);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Field inaccessible", e);
}
}
}
}
答案 2 :(得分:0)
您可以将比较方法替换为:
return typeOfObject.getField(field).get(object1).compareTo(typeOfObject.getField(field).get(object2));
并且满足异常(未找到字段,空指针,......)。
答案 3 :(得分:0)
Bean Comparator应该有用。