java - 通过属性的自定义排序ArrayList 对象

  显示原文与译文双语对照的内容

我阅读了使用比较器对ArrayLists进行排序,但在所有的示例中,人们使用了 compareTo,根据某些研究是字符串的一种方法。

我想通过一个属性对自定义对象的ArrayList进行排序: 日期对象( 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);
. . .
}

时间:

因为日期实现可比,它有一个就像 StringcompareTo 方法成功了

因此你的自定义比较器可以如下所示:


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

( compare() 方法必须返回一个 int,所以你不能直接返回 boolean,就像你正在计划的那样。)

你的排序代码就像你编写的一样:


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


问题不直接相关的几个小点:

  1. 按照惯例,类以upper-case字母开头,方法和变量以lower-case字母开头。 这就是为什么我把比较器的名字改成了 CustomComparator
  2. 使用 javadoc 。 如果你继续使用 Java,它们将是无价的。

具有自然排序顺序( 一个类号,例如)的类应该实现比较的接口,而没有自然排序顺序( 一个班级的椅子,例如)的类应该使用比较器( 或者匿名比较器类) 来提供。

两个例子:


public class Number implements Comparable<Number> {
 private int value;

 public Number(int value) { this.value = value; }
 public int compareTo(Number anotherInstance) {
 return this.value - anotherInstance.value;
 }
}

public class Chair {
 private int weight;
 private int height;

 public Chair(int weight, int height) {
 this.weight = weight;
 this.height = height;
 }
/* Omitting getters and setters */
}
class ChairWeightComparator implements Comparator<Chair> {
 public int compare(Chair chair1, Chair chair2) {
 return chair1.getWeight() - chair2.getWeight();
 }
}
class ChairHeightComparator implements Comparator<Chair> {
 public int compare(Chair chair1, Chair chair2) {
 return chair1.getHeight() - chair2.getHeight();
 }
}

使用方法:


List<Number> numbers = new ArrayList<Number>();
...
Collections.sort(numbers);

List<Chair> chairs = new ArrayList<Chair>();
//Sort by weight:
Collections.sort(chairs, new ChairWeightComparator());
//Sort by height:
Collections.sort(chairs, new ChairHeightComparator());

//You can also create anonymous comparators;
//Sort by color:
Collections.sort(chairs, new Comparator<Chair>() {
 public int compare(Chair chair1, Chair chair2) {
. . .
 }
});

对于 ArrayList,你可以使用以下代码 Fragment:


Collections.sort(studList, new Comparator<Student>(){
 public int compare(Student s1, Student s2) {
 return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
 }
});

是的,你能有两个选项还在比较项,则可比,而接口比较器接口。

这两个接口都允许不同的行为。 可以比较允许你使对象行为如同刚才描述的字符串( 事实上,字符串实现了可以比较的) 。 第二个比较器允许你做你想要做的事情。 你可以这样做:


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

这将导致 Collections.sort 方法在排序机制中使用你的比较器。 如果ArrayList中的对象实现了比较,则可以执行类似这样的操作:


Collections.sort(myArrayList);

集合类包含了许多有用的常用工具。

使用 java5,你可以对比较器使用方法引用:


import static java.util.Comparator.comparing;

Collections.sort(list, comparing(MyObject::getStartDate));


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;

public class test {

public static class Person {
 public String name;
 public int id;
 public Date hireDate;

 public Person(String iname, int iid, Date ihireDate) {
 name = iname;
 id = iid;
 hireDate = ihireDate;
 }

 public String toString() {
 return name +"" + id +"" + hireDate.toString();
 }

//Comparator
 public static class CompId implements Comparator<Person> {
 @Override
 public int compare(Person arg0, Person arg1) {
 return arg0.id - arg1.id;
 }
 }

 public static class CompDate implements Comparator<Person> {
 private int mod = 1;
 public CompDate(boolean desc) {
 if (desc) mod =-1;
 }
 @Override
 public int compare(Person arg0, Person arg1) {
 return mod*arg0.hireDate.compareTo(arg1.hireDate);
 }
 }
}

public static void main(String[] args) {
//TODO Auto-generated method stub
 SimpleDateFormat df = new SimpleDateFormat("mm-dd-yyyy");
 ArrayList<Person> people;
 people = new ArrayList<Person>();
 try {
 people.add(new Person("Joe", 92422, df.parse("12-12-2010")));
 people.add(new Person("Joef", 24122, df.parse("1-12-2010")));
 people.add(new Person("Joee", 24922, df.parse("12-2-2010")));
 } catch (ParseException e) {
//TODO Auto-generated catch block
 e.printStackTrace();
 }

 Collections.sort(people, new Person.CompId());
 System.out.println("BY ID");
 for (Person p : people) {
 System.out.println(p.toString());
 }

 Collections.sort(people, new Person.CompDate(false));
 System.out.println("BY Date asc");
 for (Person p : people) {
 System.out.println(p.toString());
 }
 Collections.sort(people, new Person.CompDate(true));
 System.out.println("BY Date desc");
 for (Person p : people) {
 System.out.println(p.toString());
 }

}

}

你可以尝试 Guava 订购:


Function<Item, Date> getStartDate = new Function<Item, Date>() {
 public Date apply(Item item) {
 return item.getStartDate();
 }
};

List<Item> orderedItems = Ordering.natural().onResultOf(getStartDate).
 sortedCopy(items);

是的,那是有可能比如在发这个回答我作为排序依据的属性类的vIndexValue


//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 ) 并将它的传送到 sort 方法释放这些资源 Arrays

你的对象也可以实现 Comparable ( 这就是字符串和Java中大多数核心库的作用),但这将定义它本身的"自然排序顺序",并且不允许你插入新的。

...