通过反射基于字段名称对List <object>进行排序

时间:2017-10-29 07:47:12

标签: java sorting

我有一个这样的模型:

public class Contact {

    private int id;

    private String firstName;

    private String lastName;

    private String address;

    private String city;

    private String state;

    private String zipCode;

    private String mobilePhone;

    private String email;

    private String dayOfBirth;

    private int age;

    public String toLine() {
        return String.format("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s", id, firstName, lastName, dayOfBirth, address, city, state, zipCode, mobilePhone, email);
    }
}

我编写了一个sort函数,通过使用反射按字段名称对List进行排序,但是field.get(contact1)没有方法compareTo。有什么方法可以实现吗? BTW,任何使toLine功能更短的方法?它似乎太长了。

    public void sortByFieldName(String fieldName, List<Contact> validContacts) throws NoSuchFieldException {

        Field field = Contact.class.getDeclaredField(fieldName);
        field.setAccessible(true);

        validContacts.stream().sorted((contact1, contact2) -> field.get(contact1).compareTo(field.get(contact2)));
}

我不想使用它,因为它似乎不灵活:

if (fieldName.equals("zipCode")) {
            validContacts.sort(Comparator.comparing(Contact::getZipCode));
        }

我删除了getter和setter,因为它太长了

1 个答案:

答案 0 :(得分:1)

你根本不需要任何反思。您可以使用Comparator#comparing

List<Contact> sortedContacts = validContacts.stream()
    .sorted(Comparator.comparing(Contact::getZipCode))
    .collect(Collectors.toList());

当然,这假设你的班级有getter方法,而你的问题并没有。如果是这种情况且可以访问字段,您也可以使用c -> c.zipCode代替Contact::getZipCode。如果两者都不是这样,并且该类看起来像你所显示的那样,那么这些字段将毫无用处,因为没有人可以访问它们(除非它是另一个类中的静态类)。

如果你确实需要使用反射 - 我真的认为你不 - 这样做,那么你就可以这样做。但我要说这是更具体的,不可重复使用。如上所示使用流API会更好:

public static List<Contact> sortByFieldName(List<Contact> list, String fieldName) throws NoSuchFieldException {
    Field field = Contact.class.getDeclaredField(fieldName);
    if (!String.class.isAssignableFrom(field.getType())) {
        throw new IllegalArgumentException("Field is not a string!");
    }

    field.setAccessible(true);
    return list.stream()
        .sorted((first, second) -> {
            try {
                String a = (String) field.get(first);
                String b = (String) field.get(second);
                return a.compareTo(b);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Error", e);
            }
        })
        .collect(Collectors.toList());
}