按属性对自定义对象的 ArrayList 进行排序

我读过有关使用 Comparator 对 ArrayList 进行排序的信息,但在所有示例中,人们都使用了compareTo ,根据一些研究,它是 String 的一种方法。

我想按自定义对象的属性之一对 ArrayList 进行排序: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);
    ...
}

答案

由于Date实现Comparable ,因此它具有String一样的compareTo方法。

因此,您的自定义Comparator可能如下所示:

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());

如果您不需要重用比较器,则编写所有这些内容的一种更短的方法是将其编写为内联匿名类:

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

自从

现在,您可以通过对Comparator使用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));

所有这些都是等效形式。

具有自然排序顺序的类(例如,一个类编号)应实现 Comparable 接口,而没有自然排序顺序的类(例如,一个类 Chair)应提供一个 Comparator(或匿名 Comparator)类)。

两个例子:

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进行排序,您可以使用以下代码片段:

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

是的你可以。比较项目有两个选项,可比较界面和比较器界面。

这两个接口都允许不同的行为。 Comparable 允许您使对象像刚刚描述的 String 一样工作(实际上,String 实现 Comparable)。第二个是 Comparator,它允许您执行要求的操作。您可以这样做:

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

这将导致 Collections.sort 方法将比较器用于其排序机制。如果 ArrayList 中的对象实现可比较,则可以改为执行以下操作:

Collections.sort(myArrayList);

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

JAVA 8 Lambda 表达式

Collections.sort(studList, (Student s1, Student s2) ->{
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
});

要么

Comparator<Student> c = (s1, s2) -> s1.firstName.compareTo(s2.firstName);
studList.sort(c)

使用 Java 8 时,可以将方法引用用作比较器:

import static java.util.Comparator.comparing;

Collections.sort(list, 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());
        }
});

用 lambda 排序

List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());

当然,具有这种美感会影响性能(平均 2 倍),但是您能找到更具可读性的代码吗?

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());
    }

}

}

JAVA 8 最好的简单方法是英语字母排序

类实施

public class NewspaperClass implements Comparable<NewspaperClass>{
   public String name;

   @Override
   public int compareTo(NewspaperClass another) {
      return name.compareTo(another.name);
   }
}

分类

Collections.sort(Your List);

如果要对包含非英文字符的字母进行排序,可以使用 “语言环境...” 下面的代码使用 “土耳其语字符排序” ...

类实施

public class NewspaperClass implements Comparator<NewspaperClass> {
   public String name;
   public Boolean isUserNewspaper=false;
   private Collator trCollator = Collator.getInstance(new Locale("tr_TR"));



   @Override
   public int compare(NewspaperClass lhs, NewspaperClass rhs) {
      trCollator.setStrength(Collator.PRIMARY);
      return trCollator.compare(lhs.name,rhs.name);
   }
}

分类

Collections.sort(your array list,new NewspaperClass());

功能与方法参考

Collections.sort方法可以使用您传递的ComparatorList进行排序。该Comparator可以使用来实现Comparator.comparing方法,其中可以传递一个方法参考作为必要Function 。幸运的是,实际代码比此描述要简单得多且短得多。

对于 Java 8:

Collections.sort(list, comparing(ClassName::getName));

要么

Collections.sort(list, comparing(ClassName::getName).reversed());

另一种方法是

Collections.sort(list, comparing(ClassName::getName, Comparator.nullsLast(Comparator.naturalOrder())));