按属性对自定义对象排序

I read about sorting ArrayLists using a Comparator but in all of the examples people used compareTo which according to some research is a method for Strings.

I wanted to sort an ArrayList of custom objects by one of their properties: a Date object (getStartDay()). Normally I compare them by item1.getStartDate().before(item2.getStartDate()) so I was wondering whether I could write something like:

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

转载于:https://stackoverflow.com/questions/2784514/sort-arraylist-of-custom-objects-by-property

csdnceshi66
必承其重 | 欲带皇冠 Answer by @Yishai in this post demonstrates elegant use of enum for custom sorting and grouped sorting (multiple arguments) utilizing comparator chaining.
大约 7 年之前 回复
csdnceshi60
℡Wang Yan Related: stackoverflow.com/questions/1814095/…
9 年多之前 回复

21个回答

Since Date implements Comparable, it has a compareTo method just like String does.

So your custom Comparator could look like this:

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

The compare() method must return an int, so you couldn't directly return a boolean like you were planning to anyway.

Your sorting code would be just about like you wrote:

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

A slightly shorter way to write all this, if you don't need to reuse your comparator, is to write it as an inline anonymous class:

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

Since

You can now write the last example in a shorter form by using a lambda expression for the Comparator:

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

And List has a sort(Comparator) method, so you can shorten this even further:

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

This is such a common idiom that there's a built-in method to generate a Comparator for a class with a Comparable key:

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

All of these are equivalent forms.

csdnceshi66
必承其重 | 欲带皇冠 This solution does not work on Android API <24. Do you guys know a solution for this?
一年多之前 回复
csdnceshi59
ℙℕℤℝ Great example thanks
一年多之前 回复
weixin_41568208
北城已荒凉 If you are using Java 8, see if you can get rid of Date in favour of one of the new and more programmer frindly classes in the java.time package.
2 年多之前 回复
csdnceshi71
Memor.の The order of String sort is asc by default when use s1.compareTo(s2) and desc when use s2.compareTo(s1)
3 年多之前 回复
weixin_41568196
撒拉嘿哟木头 better yet, use List.sort().
3 年多之前 回复
csdnceshi60
℡Wang Yan O'Connor: it throws a NullPointerException.
3 年多之前 回复
csdnceshi68
local-host what happens when o1.getStartDate() returns null?
3 年多之前 回复
weixin_41568184
叼花硬汉 you can use to compare int values like this "return o1.getDistance()-o2.getDistance();"
接近 4 年之前 回复
csdnceshi60
℡Wang Yan I didn't specify whether the comparator was declared inside another class; if it is, then yes, you would want to make it static.
大约 5 年之前 回复
csdnceshi62
"幸运的战士" Comparator class should be static :)
大约 5 年之前 回复
weixin_41568110
七度&光 I think the answer best should also include the proper way to do it in Java 8. Collections.sort(list, Comparator.comparing(MyObject::getStartDate)); which reads better and is less error prone. It's very easy to write return o1.getStartDate().compareTo(o1.getStartDate());
5 年多之前 回复
csdnceshi74
7*4 +1 for mentioning that it should return int and that you'd better to use Date#compareTo() for this. Why this isn't upvoted above the other answer is beyond me. This link may also be useful: Object Ordering Tutorial at Sun.com.
9 年多之前 回复

For sorting an ArrayList you could use the following code snippet:

Collections.sort(studList, new Comparator<Student>(){
    public int compare(Student s1, Student s2) {
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
    }
});
weixin_41568131
10.24 That sorts but gives double value for each element
接近 3 年之前 回复
csdnceshi65
larry*wei Anybody using lambda stackoverflow.com/questions/2784514/…
大约 5 年之前 回复

Yes, you can. There are two options with comparing items, the Comparable interface, and the Comparator interface.

Both of these interfaces allow for different behavior. Comparable allows you to make the object act like you just described Strings (in fact, String implements Comparable). The second, Comparator, allows you to do what you are asking to do. You would do it like this:

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

That will cause the Collections.sort method to use your comparator for it's sorting mechanism. If the objects in the ArrayList implement comparable, you can instead do something like this:

Collections.sort(myArrayList);

The Collections class contains a number of these useful, common tools.

JAVA 8 lambda expression

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

OR

Comparator<Student> c = (s1, s2) -> s1.firstName.compareTo(s2.firstName);
studList.sort(c)
csdnceshi65
larry*wei The sort order will always be ascending in your case. I've take care of sort order too in my example. Thanks Gentlemen.
3 年多之前 回复
csdnceshi56
lrony* .. or studList.sort(Comparator.comparing(Student::getFirstName));
接近 4 年之前 回复
csdnceshi58
Didn"t forge Or Collections.sort(studList, Comparator.comparing(Student::getFirstName));
大约 4 年之前 回复

With Java 8 you can use a method reference for your comparator:

import static java.util.Comparator.comparing;

Collections.sort(list, comparing(MyObject::getStartDate));
csdnceshi55
~Onlooker unfortunately android does not support Java 8, although there may be a workaround (I haven't tested it).
5 年多之前 回复
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());
    }

}

}
csdnceshi75
衫裤跑路 Just compile and run. The code is the comment and explanation.
大约 3 年之前 回复
csdnceshi62
"幸运的战士" Please add explanation to your answer.
大约 3 年之前 回复
csdnceshi79
python小菜 Welcome to stackoverflow. This question was answered some time ago. Before resurrecting old threads, please be sure your response adds something significant to the thread.
7 年多之前 回复

Since technologies appear everyday, the answer will change in the time. I took a look at LambdaJ and seems very interesting.

You can try solving these tasks with LambdaJ. You can find it here: http://code.google.com/p/lambdaj/

Here you have an example:

Sort Iterative

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

Sort with lambda

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

Of course, having this kind of beauty impacts in the performance (an average of 2 times), but can you find a more readable code?

csdnceshi60
℡Wang Yan I had to remove even items in a foreach loop other wise it gives me double of each content.
接近 3 年之前 回复
weixin_41568174
from.. it shouldn't... it's working as expected. Unless you are using a new version with a bug, which I recommend you to post it in the forum. Anyway, this answer was post prior to java 8, if you use it, then it will much better than using lambdaj
接近 3 年之前 回复
csdnceshi60
℡Wang Yan That sorts but gives double value for each element how to avoid it
接近 3 年之前 回复

Best easy way with JAVA 8 is for English Alphabetic sort

Class Implementation

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

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

Sort

  Collections.sort(Your List);

If you want to sort for alphabet that contains non English characters you can use Locale... Below code use Turkish character sort...

Class Implementation

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

Sort

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

From Java 8 and onward we don't have to use Collections.sort() directly. List interface has a default sort() method:

List<User> users = Arrays.asList(user1,user2,user3);
users.sort( (u1, u2) -> { 
return u1.getFirstName.compareTo(u2.getFirstName());}); 

See http://visvv.blogspot.in/2016/01/sorting-objects-in-java-8.html.

You can use the Bean Comparator to sort on any property in your custom class.

共21条数据 1 3 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!