我读过关于使用比较器排序数组列表的内容,但在所有的例子中,人们都使用了compareTo,根据一些研究,它是字符串的一种方法。
我想根据自定义对象的一个属性(Date对象)对其数组列表进行排序
(getStartDay())。通常我通过item1.getStartDate().before(item2.getStartDate())比较它们,所以我想知道我是否可以写一些像这样的东西:
public class CustomComparator {
public boolean compare(Object object1, Object object2) {
return object1.getStartDate().before(object2.getStartDate());
}
}
public class RandomName {
...
Collections.sort(Database.arrayList, new CustomComparator);
...
}
是的,你可以。比较项有两个选项,Comparable接口和Comparator接口。
这两个接口都允许不同的行为。Comparable允许您使对象的行为与您刚刚描述的String类似(实际上,String实现了Comparable)。第二个,Comparator,允许你做你要求做的事情。你会这样做:
Collections.sort(myArrayList, new MyComparator());
这将导致收集。方法来使用比较器的排序机制。如果数组列表中的对象实现了可比性,你可以这样做:
Collections.sort(myArrayList);
Collections类包含许多这些有用的常用工具。
我发现这些答案大部分(如果不是全部的话)依赖于底层类(Object)来实现类似的接口或具有类似的helper接口。
没有我的解决方案!下面的代码允许您通过知道对象的字符串名称来比较对象的字段。您可以很容易地修改它,不使用名称,但随后需要公开它或构造一个想要进行比较的对象。
Collections.sort(anArrayListOfSomeObjectPerhapsUsersOrSomething, new ReflectiveComparator(). new ListComparator("name"));
public class ReflectiveComparator {
public class FieldComparator implements Comparator<Object> {
private String fieldName;
public FieldComparator(String fieldName){
this.fieldName = fieldName;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public int compare(Object object1, Object object2) {
try {
Field field = object1.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
Comparable object1FieldValue = (Comparable) field.get(object1);
Comparable object2FieldValue = (Comparable) field.get(object2);
return object1FieldValue.compareTo(object2FieldValue);
}catch (Exception e){}
return 0;
}
}
public class ListComparator implements Comparator<Object> {
private String fieldName;
public ListComparator(String fieldName) {
this.fieldName = fieldName;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public int compare(Object object1, Object object2) {
try {
Field field = object1.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
Comparable o1FieldValue = (Comparable) field.get(object1);
Comparable o2FieldValue = (Comparable) field.get(object2);
if (o1FieldValue == null){ return -1;}
if (o2FieldValue == null){ return 1;}
return o1FieldValue.compareTo(o2FieldValue);
} catch (NoSuchFieldException e) {
throw new IllegalStateException("Field doesn't exist", e);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Field inaccessible", e);
}
}
}
}
函数和方法参考
的集合。sort方法可以使用传入的比较器对列表进行排序。该比较器可以使用Comparator. comparison方法实现,其中可以传递一个方法引用作为必要的函数。幸运的是,实际代码比这个描述简单得多。
对于Java 8:
Collections.sort(list, comparing(ClassName::getName));
or
Collections.sort(list, comparing(ClassName::getName).reversed());
另一种方法是
Collections.sort(list, comparing(ClassName::getName, Comparator.nullsLast(Comparator.naturalOrder())));
因为技术每天都在出现,所以答案会随着时间的推移而改变。我看了一下LambdaJ,看起来很有趣。
您可以尝试使用LambdaJ解决这些任务。你可以在这里找到它:http://code.google.com/p/lambdaj/
这里有一个例子:
这种迭代
List<Person> sortedByAgePersons = new ArrayList<Person>(persons);
Collections.sort(sortedByAgePersons, new Comparator<Person>() {
public int compare(Person p1, Person p2) {
return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
}
});
用排序
List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());
当然,拥有这种美感会影响性能(平均2次),但你能找到更可读的代码吗?