我读过关于使用比较器排序数组列表的内容,但在所有的例子中,人们都使用了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);
    ...
}

当前回答

函数和方法参考

的集合。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())));

其他回答

是的,这是可能的,例如在这个答案中,我根据类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中的大多数核心库所做的),但这将定义类本身的“自然排序顺序”,并且不允许您插入新的类。

是的,你可以。比较项有两个选项,Comparable接口和Comparator接口。

这两个接口都允许不同的行为。Comparable允许您使对象的行为与您刚刚描述的String类似(实际上,String实现了Comparable)。第二个,Comparator,允许你做你要求做的事情。你会这样做:

Collections.sort(myArrayList, new MyComparator());

这将导致收集。方法来使用比较器的排序机制。如果数组列表中的对象实现了可比性,你可以这样做:

Collections.sort(myArrayList);

Collections类包含许多这些有用的常用工具。

1.8以来的新功能是一个List.sort()方法,而不是使用Collection.sort() 直接调用mylistcontainer。sort()

下面是一个演示List.sort()特性的代码片段:

List<Fruit> fruits = new ArrayList<Fruit>();
fruits.add(new Fruit("Kiwi","green",40));
fruits.add(new Fruit("Banana","yellow",100));
fruits.add(new Fruit("Apple","mixed green,red",120));
fruits.add(new Fruit("Cherry","red",10));

// a) using an existing compareto() method
fruits.sort((Fruit f1,Fruit f2) -> f1.getFruitName().compareTo(f2.getFruitName()));
System.out.println("Using String.compareTo(): " + fruits);
//Using String.compareTo(): [Apple is: mixed green,red, Banana is: yellow, Cherry is: red, Kiwi is: green]

// b) Using a comparable class
fruits.sort((Fruit f1,Fruit f2) -> f1.compareTo(f2));  
System.out.println("Using a Comparable Fruit class (sort by color): " + fruits);
// Using a Comparable Fruit class (sort by color): [Kiwi is green, Apple is: mixed green,red, Cherry is: red, Banana is: yellow]

Fruit类是:

public class Fruit implements Comparable<Fruit>
{
    private String name;
    private String color;
    private int quantity;

    public Fruit(String name,String color,int quantity)
    { this.name = name; this.color = color; this.quantity = quantity; }

    public String getFruitName() { return name; }        
    public String getColor() { return color; }  
    public int getQuantity() { return quantity; }

    @Override public final int compareTo(Fruit f) // sorting the color
    {
        return this.color.compareTo(f.color);
    }     
    @Override public String toString()
    {   
        return (name + " is: " + color);
    }
} // end of Fruit class   

因为Date实现了Comparable,所以它有一个compareTo方法,就像String一样。

所以你的自定义比较器可以是这样的:

public class CustomComparator implements Comparator<MyObject> {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
}

compare()方法必须返回一个int值,因此不能像计划的那样直接返回一个布尔值。

你的排序代码就像你写的那样:

Collections.sort(Database.arrayList, new CustomComparator());

如果你不需要重用你的比较器,一种稍短的方法是把它写成一个内联匿名类:

Collections.sort(Database.arrayList, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
});

因为java 8

现在你可以用比较器的lambda表达式来写最后一个例子:

Collections.sort(Database.arrayList, 
                        (o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

List有一个sort(Comparator)方法,所以你可以进一步缩短:

Database.arrayList.sort((o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

这是一个非常常见的习惯用法,因此有一个内置方法可以为具有Comparable键的类生成Comparator:

Database.arrayList.sort(Comparator.comparing(MyObject::getStartDate));

所有这些都是等价的形式。

因为技术每天都在出现,所以答案会随着时间的推移而改变。我看了一下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次),但你能找到更可读的代码吗?