2011-07-27 48 views
25

Tôi có một Danh sách các đối tượng Java mà tôi muốn sắp xếp theo nhiều trường.Sắp xếp Danh sách các đối tượng theo nhiều trường

public class graduationCeremony { 
    String campus; 
    String faculty; 
    String building; 
} 

Có thể sử dụng một hoặc các giao diện ComparatorComparable để sắp xếp danh sách theo nhiều lĩnh vực? Tất cả các ví dụ tôi đã thấy sắp xếp theo chỉ một trường. Nói cách khác, người ta có thể sắp xếp theo 'khuôn viên' HOẶC 'giảng viên' HOẶC 'xây dựng'. Tôi muốn sắp xếp theo 'khuôn viên', rồi 'giảng viên', rồi 'xây dựng' (vì nó tồn tại trong SQL: ORDER BY campus, faculty, building)

Tôi nghĩ câu hỏi này là asked before, nhưng tôi không hiểu câu trả lời được chấp nhận. Ai đó có thể mở rộng hoặc minh họa câu trả lời này?

+1

Câu trả lời thứ hai cho câu hỏi đó là minh họa tốt. –

+0

Điều này có hữu ích không: http://stackoverflow.com/questions/1206073/sorting-a-collection-of-objects – jjnguy

+2

@sim, Vậy tại sao bạn không dành thời gian để hiểu, thay vì câu cá cho mã? – Moonbeam

Trả lời

48

sánh của bạn sẽ trông như thế này:

public class GraduationCeremonyComparator implements Comparator<GraduationCeremony> { 
    public int compare(GraduationCeremony o1, GraduationCeremony o2) { 
     int value1 = o1.campus.compareTo(o2.campus); 
     if (value1 == 0) { 
      int value2 = o1.faculty.compareTo(o2.faculty); 
      if (value2 == 0) { 
       return o1.building.compareTo(o2.building); 
      } else { 
       return value2; 
      } 
     } 
     return value1; 
    } 
} 

Về cơ bản nó vẫn tiếp tục so sánh từng thuộc tính liên tiếp của lớp học của bạn bất cứ khi nào so thuộc tính cho đến nay đều bình đẳng (== 0) .

+0

Cảm ơn. Lời giải thích của bạn đã giúp đồng xu giảm xuống. Tôi có một sự hiểu biết rõ ràng hơn về cách sử dụng phương thức compare() bây giờ mà trước đây tôi chưa từng có. – sim

+1

đừng quên kiểm tra null của bạn. Dòng 'int value1 = o1.campus.compareTo (o2.campus);' sẽ ném một NullPointerException nếu o1 là null –

0

Hope this helps:

import java.util.ArrayList; 
import java.util.Collections; 
import java.util.Comparator; 
import java.util.Iterator; 

class Person implements Comparable { 
    String firstName, lastName; 

    public Person(String f, String l) { 
    this.firstName = f; 
    this.lastName = l; 
    } 

    public String getFirstName() { 
    return firstName; 
    } 

    public String getLastName() { 
    return lastName; 
    } 

    public String toString() { 
    return "[ firstname=" + firstName + ",lastname=" + lastName + "]"; 
    } 

    public int compareTo(Object obj) { 
    Person emp = (Person) obj; 
    int deptComp = firstName.compareTo(emp.getFirstName()); 

    return ((deptComp == 0) ? lastName.compareTo(emp.getLastName()) : deptComp); 
    } 

    public boolean equals(Object obj) { 
    if (!(obj instanceof Person)) { 
     return false; 
    } 
    Person emp = (Person) obj; 
    return firstName.equals(emp.getFirstName()) && lastName.equals(emp.getLastName()); 
    } 
} 

class PersonComparator implements Comparator<Person> { 
    public int compare(Person emp1, Person emp2) { 
    int nameComp = emp1.getLastName().compareTo(emp2.getLastName()); 
    return ((nameComp == 0) ? emp1.getFirstName().compareTo(emp2.getFirstName()) : nameComp); 
    } 
} 

public class Main { 
    public static void main(String args[]) { 
    ArrayList<Person> names = new ArrayList<Person>(); 
    names.add(new Person("E", "T")); 
    names.add(new Person("A", "G")); 
    names.add(new Person("B", "H")); 
    names.add(new Person("C", "J")); 

    Iterator iter1 = names.iterator(); 
    while (iter1.hasNext()) { 
     System.out.println(iter1.next()); 
    } 
    Collections.sort(names, new PersonComparator()); 
    Iterator iter2 = names.iterator(); 
    while (iter2.hasNext()) { 
     System.out.println(iter2.next()); 
    } 
    } 
} 
29

Có, bạn hoàn toàn có thể thực hiện việc này. Ví dụ:

public class PersonComparator implements Comparator<Person> 
{ 
    public int compare(Person p1, Person p2) 
    { 
     // Assume no nulls, and simple ordinal comparisons 

     // First by campus - stop if this gives a result. 
     int campusResult = p1.getCampus().compareTo(p2.getCampus()); 
     if (campusResult != 0) 
     { 
      return campusResult; 
     } 

     // Next by faculty 
     int facultyResult = p1.getFaculty().compareTo(p2.getFaculty()); 
     if (facultyResult != 0) 
     { 
      return facultyResult; 
     } 

     // Finally by building 
     return p1.getBuilding().compareTo(p2.getBuilding()); 
    } 
} 

Về cơ bản bạn đang nói, "Nếu tôi có thể nói cái nào đến trước chỉ bằng cách nhìn vào khuôn viên trường (trước khi họ đến từ các trường khác nhau, và trong khuôn viên trường là lĩnh vực quan trọng nhất) sau đó tôi Nếu không, tôi sẽ tiếp tục để so sánh các khoa, một lần nữa, dừng lại nếu đủ để nói với họ ngoài. Nếu không, (nếu khuôn viên và giảng viên là như nhau cho cả hai người) chỉ cần sử dụng kết quả so sánh chúng bằng cách xây dựng. "

+0

Một thực hiện thanh lịch. – Gravity

+2

khả năng đọc .. đây phải là câu trả lời đúng! – BBaker

1

Bạn chỉ cần để lớp của bạn được kế thừa từ Comparable.

sau đó triển khai phương thức compareTo theo cách bạn muốn.

0

Bạn phải viết phương thức compareTo() của riêng bạn có mã Java cần thiết để thực hiện so sánh.

Nếu chúng ta muốn ví dụ để so sánh hai lĩnh vực công cộng, khuôn viên trường, sau đó giảng viên, chúng ta có thể làm điều gì đó như:

int compareTo(GraduationCeremony gc) 
{ 
    int c = this.campus.compareTo(gc.campus); 

    if(c != 0) 
    { 
     //sort by campus if we can 
     return c; 
    } 
    else 
    { 
     //campus equal, so sort by faculty 
     return this.faculty.compareTo(gc.faculty); 
    } 
} 

này được đơn giản hóa nhưng hy vọng mang đến cho bạn một ý tưởng. Tham khảo tài liệu So sánh và so sánh để biết thêm thông tin.

4

Nếu bạn biết trước lĩnh vực nào cần sử dụng để so sánh, thì người khác đưa ra câu trả lời đúng.
Điều bạn có thể quan tâm là sắp xếp bộ sưu tập của mình trong trường hợp bạn không biết thời gian biên dịch áp dụng tiêu chí nào. Hãy tưởng tượng bạn có một chương trình làm việc với các thành phố:



    protected Set<City> cities; 
    (...) 
    Field temperatureField = City.class.getDeclaredField("temperature"); 
    Field numberOfInhabitantsField = City.class.getDeclaredField("numberOfInhabitants"); 
    Field rainfallField = City.class.getDeclaredField("rainfall"); 
    program.showCitiesSortBy(temperatureField, numberOfInhabitantsField, rainfallField); 
    (...) 
    public void showCitiesSortBy(Field... fields) { 
     List<City> sortedCities = new ArrayList<City>(cities); 
     Collections.sort(sortedCities, new City.CityMultiComparator(fields)); 
     for (City city : sortedCities) { 
      System.out.println(city.toString()); 
     } 
    } 

nơi bạn có thể thay thế tên trường mã hóa cứng bởi tên trường rút ra từ một yêu cầu người sử dụng trong chương trình của bạn.

Trong ví dụ này, City.CityMultiComparator<City> là một lớp lồng nhau tĩnh của lớp City thực hiện Comparator:



    public static class CityMultiComparator implements Comparator<City> { 
     protected List<Field> fields; 

     public CityMultiComparator(Field... orderedFields) { 
      fields = new ArrayList<Field>(); 
      for (Field field : orderedFields) { 
       fields.add(field); 
      } 
     } 

     @Override 
     public int compare(City cityA, City cityB) { 
      Integer score = 0; 
      Boolean continueComparison = true; 
      Iterator itFields = fields.iterator(); 

      while (itFields.hasNext() && continueComparison) { 
       Field field = itFields.next(); 
       Integer currentScore = 0; 
       if (field.getName().equalsIgnoreCase("temperature")) { 
        currentScore = cityA.getTemperature().compareTo(cityB.getTemperature()); 
       } else if (field.getName().equalsIgnoreCase("numberOfInhabitants")) { 
        currentScore = cityA.getNumberOfInhabitants().compareTo(cityB.getNumberOfInhabitants()); 
       } else if (field.getName().equalsIgnoreCase("rainfall")) { 
        currentScore = cityA.getRainfall().compareTo(cityB.getRainfall()); 
       } 
       if (currentScore != 0) { 
        continueComparison = false; 
       } 
       score = currentScore; 
      } 

      return score; 
     } 
    } 


Bạn có thể muốn thêm thêm một lớp chính xác, xác định, đối với mỗi lĩnh vực, cho dù phân loại nên được tăng dần hoặc hậu duệ. Tôi đoán một giải pháp là thay thế Field đối tượng bởi các đối tượng của một lớp học mà bạn có thể gọi SortedField, chứa một đối tượng Field, cộng với lĩnh vực khác có nghĩa lên cao hoặc hậu duệ.

Các vấn đề liên quan