java - فرز ArrayList من الكائنات المخصصة حسب الممتلكات




sorting date (16)

قرأت عن فرز ArrayLists باستخدام المقارنة ولكن في جميع الأمثلة التي استخدمها الناس مقارنة compareTo والتي وفقا لبعض البحوث هي طريقة لالسترات.

أردت فرز ArrayList لكائنات مخصصة بواسطة أحد خصائصها: كائن تاريخ ( getStartDay() ). عادة item1.getStartDate().before(item2.getStartDate()) خلال 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);
    ...
}

تعبير 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 Lambda تقصر هذا النوع.

Collections.sort(stdList, (o1, o2) -> o1.getName().compareTo(o2.getName()));

انا افضل هذه العملية:

public class SortUtil
{    
    public static <T> List<T> sort(List<T> list, String sortByProperty)
    {
            Collections.sort(list, new BeanComparator(sortByProperty));
            return list;
    }
}

List<T> sortedList = SortUtil<T>.sort(unsortedList, "startDate");

إذا كانت قائمة الكائنات تحتوي على خاصية تسمى startDate ، فإنك تستخدم هذا startDate مرارًا وتكرارًا. يمكنك حتى سلسلة لهم startDate.time .

يتطلب ذلك أن يكون الكائن الخاص بك قابلاً Comparable مما يعني أنك تحتاج إلى إجراء Comparable compareTo و equals و hashCode .

نعم ، يمكن أن يكون أسرع ... ولكن الآن ليس عليك عمل مقارنة جديدة لكل نوع من أنواع الفرز. إذا كان بإمكانك توفير وقت التطوير والتخلي عن وقت التشغيل ، فقد تذهب مع هذا.


باستخدام Java 8 ، يمكنك استخدام مرجع أسلوب لمقارنك:

import static java.util.Comparator.comparing;

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

قد تكون مقتطفات التعليمات البرمجية هذه مفيدة. إذا كنت ترغب في فرز كائن في حالتي أريد الفرز حسب 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;
}

هذا يعمل. أنا استخدمها في jsp بي.


لجافا 8:

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

أو

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

يبدو أنه يعمل مع نوع تاريخ السلسلة أيضًا مثل "2015-12-14T21: 55: 51Z"

طريقة أخرى هي

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

لقد وجدت معظم هذه الإجابات ، إن لم تكن كلها ، تعتمد على الفئة الأساسية (الكائن) لتنفيذها قابلة للمقارنة أو أن يكون لها واجهة مساعدة قابلة للمقارنة.

ليس مع حلّي! تتيح لك التعليمة البرمجية التالية مقارنة حقل الكائن من خلال معرفة اسم السلسلة الخاصة به. يمكنك بسهولة تعديله لعدم استخدام الاسم ، ولكنك تحتاج إلى فضحه أو إنشاء أحد الكائنات التي تريد مقارنتها.

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

مع هذه المكتبة here يمكنك فرز قائمة الكائنات المخصصة على أعمدة متعددة. تستخدم المكتبة ميزات الإصدار 8.0. عينة متاحة أيضا هناك. هنا عينة للقيام بها

SortKeys sortKeys = new SortKeys();
sortKeys.addField("firstName")
            .addField("age", true); // This (true) will sort the age descending

// Other ways to specify a property to the sorter are
//      .addField("lastName", String.class);
//      .addField("dob", Date.class, true);

// Instantiate a ListSorter
ListSorter listSorter = new ListSorter();

// Pass the data to sort (listToSort) and the "by keys" to sort (sortKeys)
List sortedList = (List<Person>) listSorter.sortList(listToSort, sortKeys);

منذ Date تطبيق Comparable ، فإنه يحتوي على أسلوب compareTo تماماً مثل " String .

لذلك قد تبدو Comparator المخصصة لديك على 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());
    }
});

منذ java-8

يمكنك الآن كتابة المثال الأخير في نموذج أقصر باستخدام تعبير lambda Comparator :

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

وتحتوي List على طريقة sort(Comparator) ، بحيث يمكنك تقصير ذلك إلى أبعد من ذلك:

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

هذا هو عبارة شائعة مثل أن هناك طريقة مضمنة لإنشاء أداة Comparator للفئة باستخدام مفتاح قابل Comparable :

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 مرات) ، ولكن يمكنك العثور على رمز أكثر قابلية للقراءة؟


نعم تستطيع. هناك خياران لمقارنة العناصر ، وواجهة Comparable ، وواجهة Comparator .

كل من هذه الواجهات تسمح لسلوك مختلف. يتيح لك المقارن جعل الكائن يتصرف وكأنك وصفت للتو سلاسل (في الواقع ، تنفذ سلسلة قابلة للمقارنة). الثاني ، المقارن ، يسمح لك بفعل ما تطلب القيام به. سوف تفعل ذلك على النحو التالي:

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

سيؤدي ذلك إلى استخدام طريقة Collections.sort للمقارنة الخاصة بك آلية الفرز الخاصة بها. إذا كانت الكائنات الموجودة في ArrayList قابلة للتنفيذ ، يمكنك بدلاً من ذلك القيام بشيء كالتالي:

Collections.sort(myArrayList);

تحتوي فئة Collections على عدد من هذه الأدوات المفيدة والشائعة.


يجب أن تقوم الفئات التي لها ترتيب فرز طبيعي (رقم فئة ، كمثال) بتنفيذ واجهة المقارنة ، في حين يجب توفير الفئات التي ليس لها ترتيب فرز طبيعي (كرسي الفئة ، كمثال) مع المقارنة (أو المقارنة المجهولة صف دراسي).

مثالان:

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

يمكن أن يؤدي استخدام استخدام Java 8 إلى تحديد أداة Comparator في سطر واحد باستخدام Comparator.comparing()

استخدم أي من الطرق التالية:

الخيار 1:

listToBeSorted.sort(Comparator.comparing(CustomObject::getStartDate));

الخيار 2:

Collections.sort(listToBeSorted, Comparator.comparing(CustomObject::getStartDate));

يمكنك إلقاء نظرة على هذا presentation في منتدى جافا في شتوتغارت بألمانيا في عام 2016.

فقط عدد قليل من الشرائح تستخدم اللغة الألمانية ، 99٪ من المحتوى هو رمز مصدر جافا "باللغة الإنجليزية". مثل

someCollection.sort(
  OurCustomComparator
    .comparing(Person::getName)
    .thenComparing(Person::getId)
);

حيث OurCustomComparator الأساليب الافتراضية (والأفكار الأخرى المثيرة للاهتمام). كما هو موضح ، يؤدي إلى تعليمات برمجية موجزة للغاية لاختيار بعض الوسيلة لفرز. وسلسلة بسيطة للغاية (أو عكس) من معايير الفرز.

إذا كنت في java8 ، ستجد الكثير من المواد هناك للبدء.


يمكنك تجربة Ordering الجوافة:

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

يمكنك فرز باستخدام جافا 8

yourList.sort(Comparator.comparing(Classname::getName));

or

yourList.stream().forEach(a -> a.getBObjects().sort(Comparator.comparing(Classname::getValue)));




comparator