เรียงลำดับ ArrayList ของวัตถุที่กำหนดเองตามคุณสมบัติ


1145

ฉันอ่านเกี่ยวกับการเรียงลำดับ ArrayLists โดยใช้ Comparator แต่ในตัวอย่างทั้งหมดที่ผู้คนใช้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);
    ...
}

3
ที่เกี่ยวข้อง: stackoverflow.com/questions/1814095/…
BalusC

2
คำตอบโดย @Yishai ในโพสต์นี้แสดงให้เห็นถึงการใช้ enum ที่สง่างามสำหรับการเรียงลำดับแบบกำหนดเองและการเรียงลำดับที่จัดกลุ่ม
gunalmel

คำตอบ:


1538

ตั้งแต่DateการดำเนินการComparableมันมีcompareToวิธีการเช่นเดียวกับStringไม่

ดังนั้นประเพณีของคุณ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:

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

ทั้งหมดนี้เป็นรูปแบบที่เทียบเท่ากัน


33
+1 สำหรับการกล่าวถึงว่าควรส่งคืนintและคุณควรใช้Date#compareTo()สิ่งนี้ดีกว่า ทำไมนี่ไม่ upvoted เหนือคำตอบอื่น ๆ อยู่นอกเหนือฉัน การเชื่อมโยงนี้อาจจะมีประโยชน์: วัตถุการสั่งซื้อการสอนที่ Sun.com
BalusC

5
ฉันคิดว่าคำตอบที่ดีที่สุดควรรวมถึงวิธีการที่เหมาะสมใน Java 8 Collections.sort (รายการ Comparator.comparing (MyObject :: getStartDate)); ซึ่งอ่านได้ดีขึ้นและมีข้อผิดพลาดน้อยลง มันง่ายมากที่จะเขียน return o1.getStartDate () comparTo (o1.getStartDate ());
Kuba

2
ระดับ Comparator ควรจะคง :)
Jarmez De La Rocha

4
@Kuba List.sort()ดีกว่ายังใช้
shmosel

3
วิธีนี้ไม่ทำงานบน Android API <24 พวกคุณรู้จักวิธีแก้ปัญหานี้หรือไม่?
Jim Clermonts

194

คลาสที่มีลำดับการเรียงตามธรรมชาติ (หมายเลขคลาสเป็นตัวอย่าง) ควรใช้อินเตอร์เฟสที่เปรียบเทียบได้ในขณะที่คลาสที่ไม่มีลำดับการเรียงตามธรรมชาติ (คลาสของเก้าอี้เป็นตัวอย่าง) ควรจัดให้มี Comparator (หรือ Comparator แบบไม่ระบุชื่อ class)

สองตัวอย่าง:

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

ฉันลองมัน - แต่เมื่อฉันต้องการเข้าถึง ChairWeightComparator คลาสเปรียบเทียบภายนอกในคลาสอื่นฉันไม่สามารถเข้าถึงคลาสนี้ได้ (แน่นอนไม่ใช่เพราะไม่ใช่สาธารณะ) ฉันจำเป็นต้องสร้างคลาส ChairWeightComparator สาธารณะใหม่ในไฟล์แยกต่างหากหรือไม่ - ฉันเป็นคนแรกที่ลองทำสิ่งนี้หลังจากผ่านไป 3 ปีหรือเปล่า
user387184

@ user387184 - เพียงแค่ทำให้เป็นสาธารณะและวางไว้ในไฟล์ของตัวเอง (โดยเฉพาะอย่างยิ่งมันเป็นแพคเกจของตัวเองเช่นกัน) และคุณจะสามารถใช้มันได้ทุกที่ในโครงการของคุณ ไม่จำเป็นต้องสร้างคลาสเพิ่มเติม!
Björn

คุณหมายถึงสร้างไฟล์ใหม่ - ไม่ใช่คลาสและใส่รหัส: "คลาส ChairWeightComparator ใช้เครื่องมือ Comparator <Chair> {.... "?
user387184

@ user387184 ว่า - แต่มีคำสำคัญในด้านหน้าของpublic class
Björn

157

สำหรับการเรียงลำดับArrayListคุณสามารถใช้ข้อมูลโค้ดต่อไปนี้:

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


ที่แปลก แต่ให้ค่า double สำหรับแต่ละองค์ประกอบ
แซม

44

ใช่คุณสามารถ. มีสองตัวเลือกกับรายการเปรียบเทียบส่วนต่อประสานที่เปรียบเทียบได้และส่วนต่อประสานตัวเปรียบเทียบ

อินเทอร์เฟซเหล่านี้ทั้งสองอนุญาตการทำงานที่แตกต่าง Comparable ช่วยให้คุณทำให้วัตถุทำหน้าที่เหมือนกับที่คุณเพิ่งอธิบาย Strings (อันที่จริงแล้ว String จะทำการเปรียบเทียบได้) ตัวเปรียบเทียบตัวที่สองให้คุณทำสิ่งที่คุณขอให้ทำ คุณจะทำเช่นนี้:

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

ซึ่งจะทำให้วิธีการ Collections.sort ใช้การเปรียบเทียบของคุณสำหรับกลไกการเรียงลำดับ หากวัตถุใน ArrayList ใช้งานได้คุณสามารถทำสิ่งนี้แทน

Collections.sort(myArrayList);

คอลเลกชันชั้นมีจำนวนของที่มีประโยชน์เครื่องมือเหล่านี้ร่วมกัน


42

JAVA แสดงออกแลมบ์ดา 8

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)

3
หรือCollections.sort(studList, Comparator.comparing(Student::getFirstName));
โฮล

5
.. หรือstudList.sort(Comparator.comparing(Student::getFirstName));
Alexis C.

การเรียงลำดับจะเพิ่มขึ้นในกรณีของคุณเสมอ ฉันก็ดูแลเรื่องการเรียงลำดับด้วยเช่นกัน ขอบคุณสุภาพบุรุษ
ตัวเรียงลำดับ

33

ด้วย Java 8 คุณสามารถใช้การอ้างอิงเมธอดสำหรับตัวเปรียบเทียบของคุณ:

import static java.util.Comparator.comparing;

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

@ user387184 น่าเสียดายที่ android ไม่รองรับ Java 8 แม้ว่าอาจจะมีวิธีแก้ปัญหา (ฉันยังไม่ได้ทดสอบ)
assylias

14

เนื่องจากเทคโนโลยีปรากฏขึ้นทุกวันคำตอบจะเปลี่ยนแปลงในเวลา ฉันดูแลมบ์ดาจาและดูเหมือนว่าน่าสนใจมาก

คุณสามารถลองแก้งานเหล่านี้มี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 ครั้ง) แต่คุณสามารถหารหัสที่อ่านได้มากขึ้นหรือไม่?


นั่นเป็นการเรียงลำดับ แต่ให้คุณค่าสองเท่าสำหรับแต่ละองค์ประกอบว่าจะหลีกเลี่ยงได้อย่างไร
Sam

@ แซมมันไม่ควร ... มันใช้งานได้ตามที่คาดไว้ หากคุณไม่ได้ใช้เวอร์ชันใหม่ที่มีข้อผิดพลาดซึ่งฉันขอแนะนำให้คุณโพสต์ไว้ในฟอรัม อย่างไรก็ตามคำตอบนี้ถูกโพสต์ก่อนหน้าจาวา 8 ถ้าคุณใช้มันจะดีกว่าการใช้ lambdaj
Federico Piazza

ฉันต้องลบรายการที่อยู่ในลูป foreach อย่างชาญฉลาดมันทำให้ฉันมีเนื้อหาเป็นสองเท่า
Sam

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

}

}

7
ยินดีต้อนรับสู่ stackoverflow คำถามนี้ได้รับคำตอบเมื่อสักครู่ที่ผ่านมา ก่อนที่จะคืนค่าเธรดเก่าอีกครั้งโปรดตรวจสอบให้แน่ใจว่าการตอบกลับของคุณเพิ่มสิ่งที่สำคัญให้กับเธรด
Leigh

1
โปรดเพิ่มคำอธิบายลงในคำตอบของคุณ
Arashsoft

เพียงรวบรวมและเรียกใช้ รหัสคือความคิดเห็นและคำอธิบาย
CharlesW

9

วิธีที่ง่ายที่สุดกับ 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);

หากคุณต้องการเรียงลำดับตัวอักษรที่มีอักขระที่ไม่ใช่ภาษาอังกฤษคุณสามารถใช้ Locale ... ด้านล่างโค้ดใช้การจัดเรียงอักขระตุรกี ...

การใช้งานคลาส

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

9

ฟังก์ชั่นและการอ้างอิงวิธีการ

Collections.sortวิธีสามารถเรียงลำดับListใช้Comparatorคุณผ่าน ที่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())));

1
การโทรต้องใช้ระดับ API 24
akshay bhange

6

จากนั้นJava 8เป็นต้นไปเราไม่จำเป็นต้องใช้Collections.sort()โดยตรง Listอินเตอร์เฟสมีsort()วิธีการเริ่มต้น:

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

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


6

Java 8 แลมบ์ดาทำให้การเรียงลำดับสั้นลง

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

2
Collections.sort(stdList, Comparator.comparing(SomeClass::getName));
bcsb1001


5

ใช่เป็นไปได้เช่นในคำตอบนี้ฉันเรียงลำดับตามคุณสมบัติvของชั้นเรียน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;
        }
    });

หากคุณสังเกตเห็นที่นี่ฉันกำลังสร้างชั้นในที่ไม่ระบุชื่อ (ซึ่งเป็น Java สำหรับการปิด) และส่งโดยตรงไปยังsortวิธีการของชั้นเรียนArrays

วัตถุของคุณอาจนำไปใช้Comparable(นั่นคือสิ่งที่ String และห้องสมุดหลักส่วนใหญ่ใน Java ทำ) แต่นั่นจะกำหนด "ลำดับการจัดเรียงตามธรรมชาติ" ของคลาสที่ตนเองและไม่อนุญาตให้คุณเสียบใหม่


1
... แต่คุณก็สามารถแทนที่ด้วยComparator:)
BalusC

5

ฉันพบว่าส่วนใหญ่ถ้าไม่ใช่คำตอบทั้งหมดเหล่านี้จะขึ้นอยู่กับระดับพื้นฐาน (Object) เพื่อนำไปใช้เปรียบเทียบหรือมีส่วนต่อประสานที่ช่วยเหลือได้

ไม่ได้มีทางออกของฉัน! รหัสต่อไปนี้ให้คุณเปรียบเทียบฟิลด์ของวัตถุโดยรู้ชื่อสตริง คุณสามารถแก้ไขได้อย่างง่ายดายไม่ให้ใช้ชื่อ แต่จากนั้นคุณต้องเปิดเผยหรือสร้างวัตถุใดวัตถุหนึ่งที่คุณต้องการเปรียบเทียบ

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

5

คุณสามารถลองสั่ง 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);

5

คุณสามารถเรียงลำดับโดยใช้ java 8

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

or

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

3

ตัวอย่างโค้ดนี้อาจมีประโยชน์ หากคุณต้องการเรียงลำดับวัตถุในกรณีของฉันฉันต้องการจัดเรียงตามชื่อไดรฟ์ข้อมูล:

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 ของฉัน


3

ด้วยห้องสมุดนี้ที่นี่คุณสามารถเรียงลำดับรายการของวัตถุที่กำหนดเองในหลายคอลัมน์ ไลบรารีใช้คุณลักษณะเวอร์ชัน 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);

3

คุณสามารถดูงานนำเสนอนี้ได้ที่ Java Forum ใน Stuttgart ประเทศเยอรมนีในปี 2559

มีสไลด์เพียงไม่กี่ภาษาที่ใช้ภาษาเยอรมัน 99% ของเนื้อหาคือซอร์สโค้ด Java ตาม "ภาษาอังกฤษ" ชอบ

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

ที่ไหน OurCustomComparatorจะใช้วิธีการเริ่มต้น (และความคิดที่น่าสนใจอื่น ๆ ) ดังที่แสดง, นำไปสู่โค้ดที่รัดกุมมากเพื่อเลือกเมธอด getter สำหรับการเรียงลำดับ; และการโยงแบบง่าย ๆ (หรือย้อนกลับ) ของเกณฑ์การเรียงลำดับ

หากคุณเป็น java8 คุณจะพบเนื้อหามากมายที่นั่นเพื่อเริ่มต้นใช้งาน


3

ใหม่ตั้งแต่ 1.8 เป็นวิธี List.sort () แทนที่จะใช้ Collection.sort () ดังนั้นคุณจึงโทรหา mylistcontainer.sort () โดยตรง

นี่คือข้อมูลโค้ดที่แสดงให้เห็นถึงคุณสมบัติ List.sort ():

List<Fruit> fruits = new ArrayList<Fruit>();
fruits.add(new Fruit("Kiwi","green",40));
fruits.add(new Fruit("Banana","yellow",100));
fruits.add(new Fruit("Apple","mixed green,red",120));
fruits.add(new Fruit("Cherry","red",10));

// a) using an existing compareto() method
fruits.sort((Fruit f1,Fruit f2) -> f1.getFruitName().compareTo(f2.getFruitName()));
System.out.println("Using String.compareTo(): " + fruits);
//Using String.compareTo(): [Apple is: mixed green,red, Banana is: yellow, Cherry is: red, Kiwi is: green]

// b) Using a comparable class
fruits.sort((Fruit f1,Fruit f2) -> f1.compareTo(f2));  
System.out.println("Using a Comparable Fruit class (sort by color): " + fruits);
// Using a Comparable Fruit class (sort by color): [Kiwi is green, Apple is: mixed green,red, Cherry is: red, Banana is: yellow]

คลาส Fruit คือ:

public class Fruit implements Comparable<Fruit>
{
    private String name;
    private String color;
    private int quantity;

    public Fruit(String name,String color,int quantity)
    { this.name = name; this.color = color; this.quantity = quantity; }

    public String getFruitName() { return name; }        
    public String getColor() { return color; }  
    public int getQuantity() { return quantity; }

    @Override public final int compareTo(Fruit f) // sorting the color
    {
        return this.color.compareTo(f.color);
    }     
    @Override public String toString()
    {   
        return (name + " is: " + color);
    }
} // end of Fruit class   

2

คลาส customComparator ของคุณต้องใช้ java.util.Comparator เพื่อใช้ มันจะต้องเอาชนะการเปรียบเทียบ () และเท่ากับ ()

Compare () ต้องตอบคำถาม: Object 1 น้อยกว่าเท่ากับหรือมากกว่า Object 2 หรือไม่

เอกสารฉบับเต็ม: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html


1

ฉันชอบกระบวนการนี้มากกว่า:

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.timeได้

นี้ต้องใช้วัตถุของคุณจะเป็นComparableซึ่งหมายความว่าคุณต้องมีcompareTo, equalsและhashCodeการดำเนินงาน

ใช่มันอาจเร็วกว่า ... แต่ตอนนี้คุณไม่ต้องทำการเปรียบเทียบใหม่สำหรับการเรียงลำดับแต่ละประเภท หากคุณสามารถประหยัดเวลา dev และให้ขึ้นกับ runtime คุณอาจไปกับคนนี้


3
1 คำตอบนี้ได้รับก่อนหน้านี้ 2 ชั่วโมงพร้อมรหัสการทำงานที่ให้ไว้ ไม่จำเป็นต้องทำการโพสต์ซ้ำอีกครั้งและสร้างความสับสนให้กับฟอรัมโดยเฉพาะเนื่องจาก BeanComparator ไม่ใช่คลาสมาตรฐานดังนั้นจึงไม่ใช่วิธีแก้ปัญหาที่แท้จริงหากโปสเตอร์ไม่ทราบว่าคุณกำลังพูดถึงอะไร ถ้าคุณชอบคำแนะนำดั้งเดิมคุณสามารถโหวตได้และเพิ่มความคิดเห็นหากคุณต้องการ
camickr

0

ใช้ Java 8 ใช้สามารถกำหนดComparatorในหนึ่งบรรทัดโดยใช้Comparator.comparing()

ใช้วิธีใดวิธีหนึ่งต่อไปนี้:

ตัวเลือกที่ 1:

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

ตัวเลือก 2:

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

1
ดูเหมือนว่าจะซ้ำซ้อนกับคำตอบนี้จาก 3 ปีก่อน
โหระพา Bourque

1
ไม่อย่างแน่นอนตัวเลือกที่ 2 ที่นี่จะคล้ายกับตัวเลือก 1 ในคำตอบที่กล่าวถึง ฉันรู้สึกว่าคำตอบที่ต่างกันสองคำอาจมีความคล้ายคลึงกันบ้างถ้าพวกเขาตอบคำถามเดียวกัน
Sahil Chhabra

0

คลาสที่กำหนดเองของคุณสามารถใช้อินเทอร์เฟซ "ที่เปรียบเทียบได้" ซึ่งต้องใช้วิธีการเปรียบเทียบกับ ในเมธอด CompareTo คุณสามารถกำหนดความหมายของวัตถุที่มีค่าน้อยกว่าหรือมากกว่าวัตถุอื่น ดังนั้นในตัวอย่างของคุณมันอาจมีลักษณะเช่นนี้:

public class MyCustomClass implements Comparable<MyCustomClass>{

..........

 @Override
public int compareTo(MyCustomClass a) {
    if(this.getStartDate().before(a.getStartDate())){
        return -1;
    }else if(a.getStartDate().before(this.getStartDate())){
        return 1;
    }else {
        return 0;
    }
}

ตัวเลขติดลบระบุว่าสิ่งนี้มีขนาดเล็กกว่าวัตถุที่ถูกเปรียบเทียบ ตัวเลขบวกบ่งชี้ว่าสิ่งนี้มีขนาดใหญ่กว่าการเปรียบเทียบกับวัตถุและศูนย์หมายความว่าวัตถุมีค่าเท่ากัน

จากนั้นคุณสามารถใช้ collection.sort (myList) เพื่อเรียงลำดับรายการของคุณโดยไม่ต้องป้อนข้อมูลในตัวเปรียบเทียบ วิธีนี้ยังมีข้อดีของการเรียงลำดับสิ่งต่าง ๆ โดยอัตโนมัติหากคุณใช้โครงสร้างข้อมูลการรวบรวมที่เรียงลำดับเช่น TreeSet หรือ TreeMap

คุณสามารถตรวจสอบบทความนี้หากคุณต้องการอ่านเพิ่มเติมเกี่ยวกับอินเทอร์เฟซที่เปรียบเทียบได้ (การเปิดเผย: ฉันเป็นผู้เขียน;) https://nullbeans.com/the-java-comparable-interface-automatic-sort-of-collections/


0

คุณสามารถใช้ Springs PropertyComparatorหากคุณมีเส้นทางคุณสมบัติ String ไปยังคุณสมบัติ (ซ้อนกัน) ที่คุณต้องการเรียงลำดับ:

List<SomeObject> list = ...;
PropertyComparator<HitWithInfo> propertyComparator = new PropertyComparator<>(
    "property.nested.myProperty", false, true);
list.sort(propertyComparator);

ข้อเสียเปรียบคือตัวเปรียบเทียบนี้จะละเว้นคุณสมบัติที่ไม่มีอยู่หรือไม่สามารถเข้าถึงได้และจะจัดการสิ่งนี้เป็นค่า Nullสำหรับการเปรียบเทียบ ซึ่งหมายความว่าคุณควรทดสอบตัวเปรียบเทียบดังกล่าวอย่างรอบคอบหรือตรวจสอบความมีอยู่ของเส้นทางคุณสมบัติอย่างใด


0

การใช้ java-8 stream api คุณสามารถจัดเรียงArrayListโดย:

 Comparator<Person> birthdayComparator = Comparator.comparing(Person::getBirthday);
 List<Person> sortedList = list.stream().sorted(birthdayComparator).collect(toList());

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.