我读过关于使用比较器排序数组列表的内容,但在所有的例子中,人们都使用了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);
...
}
是的,这是可能的,例如在这个答案中,我根据类IndexValue的属性v进行排序
// Sorting by property v using a custom comparator.
Arrays.sort( array, new Comparator<IndexValue>(){
public int compare( IndexValue a, IndexValue b ){
return a.v - b.v;
}
});
如果您注意到这里,我正在创建一个匿名的内部类(这是用于闭包的Java),并将其直接传递给类Arrays的排序方法
您的对象也可以实现Comparable(这是String和Java中的大多数核心库所做的),但这将定义类本身的“自然排序顺序”,并且不允许您插入新的类。
我发现这些答案大部分(如果不是全部的话)依赖于底层类(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感兴趣,你可以在那里找到很多材料来开始学习。
因为技术每天都在出现,所以答案会随着时间的推移而改变。我看了一下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次),但你能找到更可读的代码吗?