Cách sắp xếp Danh sách <Đối tượng> theo thứ tự bảng chữ cái bằng cách sử dụng trường Tên đối tượng


102

Tôi có một Danh sách các đối tượng như vậy. List<Object> pTôi muốn sắp xếp danh sách này theo thứ tự bảng chữ cái bằng cách sử dụng trường Tên đối tượng. Đối tượng chứa 10 trường và trường tên là một trong số đó.

if (list.size() > 0) {
    Collections.sort(list, new Comparator<Campaign>() {
        @Override
        public int compare(final Object object1, final Object object2) {
        return String.compare(object1.getName(), object2.getName());
        }
    } );
}

Nhưng không có gì giống như String.compare ..?


3
Bạn định lấy tên như thế nào? - Objects không có tên. Bạn có nghĩa là sử dụng .toString()?
Matt Fenwick

object1object2cần phải thuộc loại Campaign, và chức năng so sánh là object1.getName().compareTo(object2.getName()).
Bart van Heukelom

Bạn trộn List<Object>Comparator<Campaign>. Bạn không thể làm điều đó. Hoặc bạn có List<Object>Comparator<Object>hoặc List<Campaign>Comparator<Campaign>
viktor

Câu trả lời:


230

Từ mã của bạn, có vẻ như mã của bạn Comparatorđã được tham số hóa với Campaign. Điều này sẽ chỉ hoạt động với List<Campaign>. Ngoài ra, phương pháp bạn đang tìm kiếm là compareTo.

if (list.size() > 0) {
  Collections.sort(list, new Comparator<Campaign>() {
      @Override
      public int compare(final Campaign object1, final Campaign object2) {
          return object1.getName().compareTo(object2.getName());
      }
  });
}

Hoặc nếu bạn đang sử dụng Java 1.8

list
  .stream()
  .sorted((object1, object2) -> object1.getName().compareTo(object2.getName()));

Một nhận xét cuối cùng - không có ích gì khi kiểm tra kích thước danh sách. Sắp xếp sẽ hoạt động trên một danh sách trống.


2
Tôi nghĩ đây là câu trả lời tốt nhất chắt lọc mọi thứ thành những gì OP đang tìm kiếm. Và từ các nhận xét, tôi nghĩ anh ấy muốn không phân biệt chữ hoa chữ thường, vì vậy chỉ cần chuyển so sánhTo sang so sánhToIgnoreCase
Greg Case

Cải thiện nhỏ trong giải pháp đầu tiên: chúng tôi có thể làm nếu (list.size ()> 1) - đối với 1 mục không cần phải phân loại ..
Rami Yampolsky

12
Bạn có thể sử dụngComparator.comparing(Campaign::getName)
Jose Da Silva

4
list.sort((object1, object2) -> object1. getName().compareTo(object2. getName()));đã làm việc cho tôi
Lucas

1
Hãy thử sử dụng sortedList = list.stream().sort((object1, object2) -> object1. getName().compareTo(object2. getName()))..collect(Collectors.toList());để có một danh sách được sắp xếp mới
Lukas

16

Cách chính xác nhất để sắp xếp các chuỗi theo thứ tự bảng chữ cái là sử dụng Collator, vì tính quốc tế. Một số ngôn ngữ có thứ tự khác nhau do có ít ký tự phụ, v.v.

   Collator collator = Collator.getInstance(Locale.US);
   if (!list.isEmpty()) {
    Collections.sort(list, new Comparator<Campaign>() {
        @Override
        public int compare(Campaign c1, Campaign c2) {
            //You should ensure that list doesn't contain null values!
            return collator.compare(c1.getName(), c2.getName());
        }
       });
   }

Nếu bạn không quan tâm đến việc sử dụng quốc tế hóa string.compare(otherString).

   if (!list.isEmpty()) {
    Collections.sort(list, new Comparator<Campaign>() {
        @Override
        public int compare(Campaign c1, Campaign c2) {
            //You should ensure that list doesn't contain null values!
            return c1.getName().compare(c2.getName());
        }
       });
   }

11

Hãy xem Collections.sort()Comparatorgiao diện.

So sánh chuỗi có thể được thực hiện với object1.getName().compareTo(object2.getName())hoặc object2.getName().compareTo(object1.getName())(tùy thuộc vào hướng sắp xếp bạn muốn).

Nếu bạn muốn phân loại là trường hợp bất khả tri, hãy làm object1.getName().toUpperCase().compareTo(object2.getName().toUpperCase()).


và làm thế nào để bạn đề xuất trích xuất trường đó được gọi namatừ Objectloại? câu trả lời này không hoàn chỉnh.
amit

Trích xuất tên phụ thuộc vào loại đối tượng. Tôi cho rằng nó chỉ là một loại trình giữ chỗ. Nếu bạn không thể đưa ra một kiểu cụ thể hơn, bạn có thể ngừng sử dụng phản chiếu.
tobiasbayer


7
public class ObjectComparator implements Comparator<Object> {

    public int compare(Object obj1, Object obj2) {
        return obj1.getName().compareTo(obj2.getName());
    }

}

Vui lòng thay thế Đối tượng bằng lớp của bạn có chứa trường tên

Sử dụng:

ObjectComparator comparator = new ObjectComparator();
Collections.sort(list, comparator);

Tôi đã làm điều này nhưng còn hơn "bài kiểm tra" sẽ đến trước "Tìm kiếm".: (((
Saurabh Kumar

nếu bạn muốn o làm ngược lại phân loại, chỉ cần thay thế obj1.getName().compareTo(obj2.getName()với obj2.getName().compareTo(obj1.getName()trong lớp so sánh
Jan Vorcak

2

cái gì đó như

  List<FancyObject> theList =  ;
  Collections.sort (theList,
                    new Comparator<FancyObject> ()
                    { int compare (final FancyObject a, final FancyObject d)
                          { return (a.getName().compareTo(d.getName())); }});

2

Đây là phiên bản câu trả lời của Robert B hoạt động List<T>và sắp xếp theo thuộc tính Chuỗi được chỉ định của đối tượng bằng cách sử dụng Phản chiếu và không có thư viện bên thứ ba

/**
 * Sorts a List by the specified String property name of the object.
 * 
 * @param list
 * @param propertyName
 */
public static <T> void sortList(List<T> list, final String propertyName) {

    if (list.size() > 0) {
        Collections.sort(list, new Comparator<T>() {
            @Override
            public int compare(final T object1, final T object2) {
                String property1 = (String)ReflectionUtils.getSpecifiedFieldValue (propertyName, object1);
                String property2 = (String)ReflectionUtils.getSpecifiedFieldValue (propertyName, object2);
                return property1.compareToIgnoreCase (property2);
            }
        });
    }
}


public static Object getSpecifiedFieldValue (String property, Object obj) {

    Object result = null;

    try {
        Class<?> objectClass = obj.getClass();
        Field objectField = getDeclaredField(property, objectClass);
        if (objectField!=null) {
            objectField.setAccessible(true);
            result = objectField.get(obj);
        }
    } catch (Exception e) {         
    }
    return result;
}

public static Field getDeclaredField(String fieldName, Class<?> type) {

    Field result = null;
    try {
        result = type.getDeclaredField(fieldName);
    } catch (Exception e) {
    }       

    if (result == null) {
        Class<?> superclass = type.getSuperclass();     
        if (superclass != null && !superclass.getName().equals("java.lang.Object")) {       
            return getDeclaredField(fieldName, type.getSuperclass());
        }
    }
    return result;
}

2

Bạn có thể sử dụng sortThisBy()từ Bộ sưu tập Eclipse :

MutableList<Campaign> list = Lists.mutable.empty();
list.sortThisBy(Campaign::getName);

Nếu bạn không thể thay đổi loại danh sách từ List:

List<Campaign> list = new ArrayList<>();
ListAdapter.adapt(list).sortThisBy(Campaign::getName);

Lưu ý: Tôi là người đóng góp cho Bộ sưu tập Eclipse.


2

Thử cái này:

List< Object> myList = x.getName;
myList.sort(Comparator.comparing(Object::getName));

FYI nếu bạn đang làm điều này trong Android, nó yêu cầu ít nhất API cấp 24
MSpeed

1

Nếu các đối tượng của bạn có một tổ tiên chung nào đó [hãy để nó là T], bạn nên sử dụng List<T>thay vì List<Object>và triển khai Bộ so sánh cho T này, sử dụng trường tên.

Nếu bạn không có tổ tiên chung, bạn có thể triển khai Đối thủ cạnh tranh và sử dụng phản chiếu để trích xuất tên, Lưu ý rằng sử dụng phản chiếu không an toàn, không được đề xuất và có hiệu suất kém, nhưng nó cho phép bạn truy cập vào tên trường mà không biết bất cứ điều gì về loại thực tế của đối tượng [ngoài thực tế là nó có một trường có tên liên quan]

Trong cả hai trường hợp, bạn nên sử dụng Collections.sort () để sắp xếp.


1

Tôi đã tìm thấy một cách khác để làm loại.

if(listAxu.size() > 0){
    Collections.sort(listAxu, Comparator.comparing(IdentityNamed::getDescricao));
}

0

Đây là giả sử một danh sách YourClassthay vì Object, như amit giải thích .

Bạn có thể sử dụng bit này từ thư viện Google Guava:

Collections.sort(list, Ordering.natural()
  .onResultOf(new Function<String,YourClass>() {
  public String call(YourClass o) {
     return o.getName();
  }))
  .nullsLast();

Các câu trả lời khác mà đề cập đến Comparatorkhông phải là không chính xác, vì Orderingthực hiện Comparator. Giải pháp này, theo ý kiến ​​của tôi, dễ dàng hơn một chút, mặc dù nó có thể khó hơn nếu bạn là người mới bắt đầu và không quen sử dụng thư viện và / hoặc "lập trình chức năng".

Sao chép một cách đáng xấu hổ từ câu trả lời này cho câu hỏi của riêng tôi.


Đây là cách tôi muốn làm, nhưng có thể là quá nhiều đối với OP.
Greg Case

0

Sử dụng lựa chọn Sắp xếp

for(int i = list.size() - 1; i > 0; i--){

  int max = i

  for(int j = 0; j < i; j++){
      if(list.get(j).getName().compareTo(list.get(j).getName()) > 0){
            max= j;
      }
  }

  //make the swap
  Object temp = list.get(i);
  list.get(i) = list.get(max);
  list.get(max) = temp;

}

(1) Tại sao anh ta lại phát minh ra bánh xe? có chuyện gì Collections.sort()vậy (2) danh sách thuộc loại List<Object>và do đó list.get(j).getName()sẽ không biên dịch. (3) giải pháp này là O (n ^ 2), trong khi sử dụng Collections.sort()là giải pháp O (nlogn) tốt hơn.
amit

0

Nếu bạn đang sử dụng một List<Object>để giữ các đối tượng của một kiểu con có trường tên (cho phép gọi kiểu con NamedObject), bạn sẽ cần truyền xuống các phần tử danh sách để truy cập tên. Bạn có 3 tùy chọn, trong đó tốt nhất là tùy chọn đầu tiên:

  1. Đừng sử dụng a List<Object>ngay từ đầu nếu bạn có thể giúp nó - giữ các đối tượng đã đặt tên của bạn trongList<NamedObject>
  2. Sao chép các List<Object>phần tử của bạn vào một List<NamedObject>, dự báo xuống trong quá trình, thực hiện sắp xếp, sau đó sao chép chúng trở lại
  3. Thực hiện dự báo xuống trong Bộ so sánh

Tùy chọn 3 sẽ giống như sau:

Collections.sort(p, new Comparator<Object> () {
        int compare (final Object a, final Object b) {
                return ((NamedObject) a).getName().compareTo((NamedObject b).getName());
        }
}

0
if(listAxu.size() > 0){
     Collections.sort(listAxu, new Comparator<Situacao>(){
        @Override
        public int compare(Situacao lhs, Situacao rhs) {            
            return lhs.getDescricao().compareTo(rhs.getDescricao());
        }
    });
 }

1
Bạn quan tâm đến việc xây dựng chi tiết hơn là chỉ bán mã trong một câu hỏi 3 năm tuổi?
Holloway

0

Câu trả lời của @ Victor phù hợp với tôi và đăng lại nó ở đây trong Kotlin trong trường hợp hữu ích cho người khác đang sử dụng Android.

if (list!!.isNotEmpty()) {
   Collections.sort(
     list,
     Comparator { c1, c2 -> //You should ensure that list doesn't contain null values!
     c1.name!!.compareTo(c2.name!!)
   })
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.