我读过关于使用比较器排序数组列表的内容,但在所有的例子中,人们都使用了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);
...
}
我发现这些答案大部分(如果不是全部的话)依赖于底层类(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);
}
}
}
}
您可以在2016年德国斯图加特的Java论坛上看一看这个演讲。
只有少数幻灯片使用德语,99%的内容是“基于英语”的Java源代码;就像
someCollection.sort(
OurCustomComparator
.comparing(Person::getName)
.thenComparing(Person::getId)
);
其中OurCustomComparator使用默认方法(和其他有趣的想法)。如图所示,导致非常简洁的代码,以选择一些getter方法进行排序;以及超级简单的排序标准链接(或反转)。
如果你对java8感兴趣,你可以在那里找到很多材料来开始学习。
您的自定义类可以实现“Comparable”接口,这需要CompareTo方法的实现。在CompareTo方法中,您可以定义一个对象小于或大于另一个对象意味着什么。所以在你的例子中,它看起来是这样的:
public class MyCustomClass implements Comparable<MyCustomClass>{
..........
@Override
public int compareTo(MyCustomClass a) {
if(this.getStartDate().before(a.getStartDate())){
return -1;
}else if(a.getStartDate().before(this.getStartDate())){
return 1;
}else {
return 0;
}
}
负数表示它小于与之比较的对象。正数表示这比对象的比较大,零表示对象相等。
然后,可以使用collections.sort(myList)对列表进行排序,而不必输入比较器。如果使用TreeSet或TreeMap等已排序的集合数据结构,则此方法还具有自动排序的优点。
如果您想阅读更多关于Comparable接口的信息,可以查看这篇文章(披露:我是作者;))
https://nullbeans.com/the-java-comparable-interface-automatic-sort-of-collections/