Java 对列表排序<;对象>;基于反射的字段名
我有一个这样的模型:Java 对列表排序<;对象>;基于反射的字段名,java,sorting,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 mob
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);
}
}
我编写了一个排序函数,通过使用反射按字段名对列表进行排序,但是field.get(contact1)
没有方法比较。有什么办法可以实现吗?顺便说一句,有没有办法缩短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)));
}
我删除了getter和setter,因为它太长了,根本不需要任何反射。您可以使用
Comparator#comparing
进行以下操作:
List<Contact> sortedContacts = validContacts.stream()
.sorted(Comparator.comparing(Contact::getZipCode))
.collect(Collectors.toList());
你根本不需要任何思考。您可以使用
Comparator#comparing
进行以下操作:
List<Contact> sortedContacts = validContacts.stream()
.sorted(Comparator.comparing(Contact::getZipCode))
.collect(Collectors.toList());
我知道这一点,但是如果使用它,我们必须使用if-else,就像我说的,我想做一个通用的排序函数,我可以传递字段名,并按照该字段对列表进行排序,而不需要if-else。我的模型有getter和setter,但我删除了它们,因为没有if/else太长了。在某个时候,您需要传递字段的名称,对吗?因此,不要在那里传递字符串,只需传递
Contact::getZipCode
句柄即可。很抱歉,我没有理解。如果我想按id排序怎么办?会是这样的,对吗List sortedContacts=validContacts.stream().sorted(Comparator.comparing(Contact::getId)).collect(Collectors.toList())所以我的方法是:if(fieldName.equals(“id”){//Contact::getId}或者if(fieldName.equals(“zipCode”){//Contact::getZipCode}
在我的回答中,你不再需要你自己的方法。它已经根据字段进行了排序,这就是Comparator#comparing
所做的:它从要比较的对象中提取一个字段。您的sortByFieldName
根本不需要。@ThachHuynh如果您确实想继续下去,我还添加了一个反射版本。但正如我所说,您根本不需要自定义方法,只需使用Comparator.comparating(Contact::getXyz)
,如我在回答中所述。如果它解决了你的问题,也请接受答案。我知道这一点,但如果使用它,我们必须使用if-else,就像我说的,我想做一个通用的排序函数,我可以传递字段名并按该字段对列表进行排序,而不需要if-else。我的模型有getter和setter,但我删除了它们,因为没有if/else太长了。在某个时候,您需要传递字段的名称,对吗?因此,不要在那里传递字符串,只需传递Contact::getZipCode
句柄即可。很抱歉,我没有理解。如果我想按id排序怎么办?会是这样的,对吗List sortedContacts=validContacts.stream().sorted(Comparator.comparing(Contact::getId)).collect(Collectors.toList())所以我的方法是:if(fieldName.equals(“id”){//Contact::getId}或者if(fieldName.equals(“zipCode”){//Contact::getZipCode}
在我的回答中,你不再需要你自己的方法。它已经根据字段进行了排序,这就是Comparator#comparing
所做的:它从要比较的对象中提取一个字段。您的sortByFieldName
根本不需要。@ThachHuynh如果您确实想继续下去,我还添加了一个反射版本。但正如我所说,您根本不需要自定义方法,只需使用Comparator.comparating(Contact::getXyz)
,如我在回答中所述。如果答案解决了你的问题,也请接受。
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());
}