2009-12-22 31 views

Trả lời

14
String[] s = {"a", "x", "y"}; 
Arrays.sort(s, new Comparator<String>() { 

    @Override 
    public int compare(String o1, String o2) { 
     return o2.compareTo(o1); 
    } 
}); 
System.out.println(Arrays.toString(s)); 

-> [y, x, a] 

Bây giờ bạn phải triển khai Trình so sánh cho lớp Người của bạn. Một cái gì đó như (cho thứ tự tăng dần): compare(Person a, Person b) = a.id < b.id ? -1 : (a.id == b.id) ? 0 : 1 hoặc Integer.valueOf(a.id).compareTo(Integer.valueOf(b.id)).

Để giảm thiểu sự nhầm lẫn, bạn nên triển khai Bộ so sánh gia tăng và chuyển đổi nó thành bộ so sánh giảm dần với trình bao bọc (like this) new ReverseComparator<Person>(new PersonComparator()).

+0

Bây giờ, đó là một ví dụ hơi khó hiểu, vì String thực hiện Comparable. Và đó là -1 không phải là điều đáng sợ nhất. – Bozho

+1

Đối số tốt nhất so với -1 * x là '-1 * Integer.MIN_VALUE == Integer.MIN_VALUE'. Mà không phải là những gì bạn muốn. Tôi đổi chỗ các đối số dễ dàng hơn. –

+1

Và tôi đoán đó là một ReverseComparator, thay vì Reserve ... –

0

Lớp java.util.Collection s có phương pháp sắp xếp lấy danh sách và tùy chỉnh Comparator. Bạn có thể định nghĩa Comparator của riêng bạn để sắp xếp đối tượng Person của bạn theo cách bạn muốn.

0
package com.test; 

import java.util.Arrays; 

public class Person implements Comparable { 

private int age; 

private Person(int age) { 
    super(); 
    this.age = age; 
} 

public int getAge() { 
    return age; 
} 

public void setAge(int age) { 
    this.age = age; 
} 

@Override 
public int compareTo(Object o) { 
    Person other = (Person)o; 
    if (this == other) 
     return 0; 
    if (this.age < other.age) return 1; 
    else if (this.age == other.age) return 0; 
    else return -1; 

} 

public static void main(String[] args) { 

    Person[] arr = new Person[4]; 
    arr[0] = new Person(50); 
    arr[1] = new Person(20); 
    arr[2] = new Person(10); 
    arr[3] = new Person(90); 

    Arrays.sort(arr); 

    for (int i=0; i < arr.length; i++) { 
     System.out.println(arr[i].age); 
    } 
} 

} 

Đây là một cách để thực hiện.

13

Tôi sẽ tạo một trình so sánh cho lớp người có thể được parametrized với một hành vi phân loại nhất định. Ở đây tôi có thể đặt thứ tự sắp xếp nhưng nó có thể được sửa đổi để cho phép sắp xếp cho các thuộc tính của người khác.

public class PersonComparator implements Comparator<Person> { 

    public enum SortOrder {ASCENDING, DESCENDING} 

    private SortOrder sortOrder; 

    public PersonComparator(SortOrder sortOrder) { 
    this.sortOrder = sortOrder; 
    } 

    @Override 
    public int compare(Person person1, Person person2) { 
    Integer age1 = person1.getAge(); 
    Integer age2 = person2.getAge(); 
    int compare = Math.signum(age1.compareTo(age2)); 

    if (sortOrder == ASCENDING) { 
     return compare; 
    } else { 
     return compare * (-1); 
    } 
    } 
} 

(hy vọng nó biên dịch bây giờ, tôi không có IDE hoặc JDK trong tầm tay, mã hóa 'mù')

Sửa

Nhờ Thomas, biên tập mã. Tôi sẽ không nói rằng việc sử dụng Math.signum là tốt, hiệu suất, hiệu quả, nhưng tôi muốn giữ nó như một lời nhắc nhở, rằng phương thức compareTo có thể trả về bất kỳ số nguyên nào và nhân với (-1) sẽ thất bại nếu thực hiện trả về Integer.MIN_INTEGER ... Và tôi đã gỡ bỏ setter vì nó đủ rẻ để xây dựng một PersonComparator mới ngay khi cần thiết.

Nhưng tôi giữ quyền anh vì nó cho thấy tôi dựa vào triển khai So sánh hiện có. Có thể đã làm một cái gì đó như Comparable<Integer> age1 = new Integer(person1.getAge()); nhưng trông quá xấu xí. Ý tưởng là để hiển thị một mô hình có thể dễ dàng thích nghi với các thuộc tính Person khác, như tên, ngày sinh như ngày và vân vân.

+4

Ngày xửa ngày xưa có một thói quen tốt để lại một bình luận để giúp tác giả vừa được bình chọn để cải thiện thông điệp của mình. –

+0

Tôi đã không downvote, nhưng 'so sánh * (-1)' là dễ bị tràn. Tôi đã làm sai lầm tương tự trong bài viết đầu tiên của tôi. –

+0

Và SortOrder phải được đặt trong hàm tạo và là giá trị cuối cùng. Sử dụng một wrapper là một cách tiếp cận tốt hơn tôi cho rằng: 'new Reverse (new PersonComparator())' –

4

Sử dụng bộ sưu tập của Google:

class Person { 
private int age; 

public static Function<Person, Integer> GET_AGE = 
    new Function<Person, Integer> { 
    public Integer apply(Person p) { return p.age; } 
    }; 

} 

public static void main(String[] args) { 
ArrayList<Person> people; 
// Populate the list... 

Collections.sort(people, Ordering.natural().onResultOf(Person.GET_AGE).reverse()); 
} 
+2

Overshooting với phong cách :) – Esko

58

Đối whats giá trị của nó ở đây là câu trả lời tiêu chuẩn của tôi. Điều duy nhất mới ở đây là sử dụng Collections.reverseOrder(). Thêm vào đó nó đặt tất cả lời đề nghị vào một ví dụ:

/* 
** Use the Collections API to sort a List for you. 
** 
** When your class has a "natural" sort order you can implement 
** the Comparable interface. 
** 
** You can use an alternate sort order when you implement 
** a Comparator for your class. 
*/ 
import java.util.*; 

public class Person implements Comparable<Person> 
{ 
    String name; 
    int age; 

    public Person(String name, int age) 
    { 
     this.name = name; 
     this.age = age; 
    } 

    public String getName() 
    { 
     return name; 
    } 

    public int getAge() 
    { 
     return age; 
    } 

    public String toString() 
    { 
     return name + " : " + age; 
    } 

    /* 
    ** Implement the natural order for this class 
    */ 
    public int compareTo(Person p) 
    { 
     return getName().compareTo(p.getName()); 
    } 

    static class AgeComparator implements Comparator<Person> 
    { 
     public int compare(Person p1, Person p2) 
     { 
      int age1 = p1.getAge(); 
      int age2 = p2.getAge(); 

      if (age1 == age2) 
       return 0; 
      else if (age1 > age2) 
       return 1; 
      else 
       return -1; 
     } 
    } 

    public static void main(String[] args) 
    { 
     List<Person> people = new ArrayList<Person>(); 
     people.add(new Person("Homer", 38)); 
     people.add(new Person("Marge", 35)); 
     people.add(new Person("Bart", 15)); 
     people.add(new Person("Lisa", 13)); 

     // Sort by natural order 

     Collections.sort(people); 
     System.out.println("Sort by Natural order"); 
     System.out.println("\t" + people); 

     // Sort by reverse natural order 

     Collections.sort(people, Collections.reverseOrder()); 
     System.out.println("Sort by reverse natural order"); 
     System.out.println("\t" + people); 

     // Use a Comparator to sort by age 

     Collections.sort(people, new Person.AgeComparator()); 
     System.out.println("Sort using Age Comparator"); 
     System.out.println("\t" + people); 

     // Use a Comparator to sort by descending age 

     Collections.sort(people, 
      Collections.reverseOrder(new Person.AgeComparator())); 
     System.out.println("Sort using Reverse Age Comparator"); 
     System.out.println("\t" + people); 
    } 
} 
+0

điều này thực sự làm việc cho tôi, và nó cũng là một giải pháp rất dễ dàng (chỉ một dòng). –

+0

Ví dụ hoàn hảo! Cảm ơn. –

+0

Có cách nào để sắp xếp các chuỗi trong một TreeSet bằng cách sử dụng một bộ so sánh như thế này? Cùng một điều, mọi người theo độ tuổi. – Zeff520

82

Bạn có thể làm các loại giảm dần của một lớp người dùng định nghĩa theo cách này trọng phương pháp compare(),

Collections.sort(unsortedList,new Comparator<Person>() { 
    @Override 
    public int compare(Person a, Person b) { 
     return b.getName().compareTo(a.getName()); 
    } 
}); 

Hoặc bằng cách sử dụng Collection.reverse() để sắp xếp giảm dần khi người dùng Hoàng tử được đề cập trong his comment.

Và bạn có thể làm sắp xếp tăng dần như thế này,

Collections.sort(unsortedList,new Comparator<Person>() { 
    @Override 
    public int compare(Person a, Person b) { 
     return a.getName().compareTo(b.getName()); 
    } 
}); 

Thay thế mã trên với một biểu thức Lambda (Java 8 trở đi), chúng tôi có được súc tích:

Collections.sort(personList, (Person a, Person b) -> b.getName().compareTo(a.getName())); 

Tính đến Java 8, Danh sách có phương thức sort() mất Comparator làm tham số (ngắn gọn hơn):

personList.sort((a,b)->b.getName().compareTo(a.getName())); 

Ở đây, ab được suy ra dưới dạng Kiểu người theo biểu thức lambda.

+18

Hoặc bạn chỉ có thể sử dụng 'Collections.reverseOrder (...)' để sắp xếp giảm dần. – Prince

+1

@Prince Không phải là một fan hâm mộ của phương pháp đó, nó buộc tôi phải xem xét phương pháp ban đầu để xem cách mọi thứ được sắp xếp để bắt đầu (un-reversed.) –

+1

Đáng nói rằng 'compareToIgnoreCase' cũng tiện dụng khi so sánh các đối tượng' String' , thường xuyên hơn tôi không sử dụng điều này thay vì chỉ 'compareTo' –

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