按任何成员的字段排序任何对象的列表/向量?

时间:2011-08-09 04:33:10

标签: java android stack-overflow

这已被问了一千次,但我看到的所有答案都不适用于传递的对象,它们总是硬编码到哪个对象和哪个字段。我正在寻找一种基于字符串字段对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;
        }
    }

4 个答案:

答案 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应该有用。