按属性对自定义对象排序

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个回答

Yes, that's possible for instance in this answer I sort by the property v of the class IndexValue

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

If you notice here I'm creating a anonymous inner class ( which is the Java for closures ) and passing it directly to the sort method of the class Arrays

Your object may also implement Comparable ( that's what String and most of the core libraries in Java does ) but that would define the "natural sort order" of the class it self, and doesn't let you plug new ones.

csdnceshi76
斗士狗 ...but which you can just override with Comparator :)
9 年多之前 回复

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.

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
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 年多之前 回复

This code snippets might be useful. If you want to sort an Object in my case I want to sort by VolumeName:

public List<Volume> getSortedVolumes() throws SystemException {
    List<Volume> volumes = VolumeLocalServiceUtil.getAllVolumes();
    Collections.sort(volumes, new Comparator<Volume>() {
        public int compare(Volume o1, Volume o2) {
            Volume p1 = (Volume) o1;
            Volume p2 = (Volume) o2;
            return p1.getVolumeName().compareToIgnoreCase(
                    p2.getVolumeName());
        }
    });
    return volumes;
}

This works. I use it in my jsp.

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 年多之前 回复

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

I found most if not all of these answers rely on the underlying class (Object) to implement comparable or to have a helper comparable interface.

Not with my solution! The following code lets you compare object's field by knowing their string name. You could easily modify it not to use the name, but then you need to expose it or construct one of the Objects you want to compare against.

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

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

your customComparator class must implement java.util.Comparator in order to be used. it must also overide compare() AND equals()

compare() must answer the question: Is object 1 less than, equal to or greater than object 2?

full docs: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html

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.
接近 4 年之前 回复
csdnceshi56
lrony* .. or studList.sort(Comparator.comparing(Student::getFirstName));
接近 4 年之前 回复
csdnceshi58
Didn"t forge Or Collections.sort(studList, Comparator.comparing(Student::getFirstName));
4 年多之前 回复
共21条数据 首页 2 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!