【问题标题】:How to sort a Collection<T>?如何对 Collection<T> 进行排序?
【发布时间】:2010-03-19 12:38:28
【问题描述】:

我有一个通用的Collection,我正在尝试弄清楚如何对其中包含的项目进行排序。我尝试了一些方法,但其中任何一个都无法正常工作。

【问题讨论】:

    标签: java sorting collections


    【解决方案1】:

    集合本身没有预定义的顺序,因此您必须将它们转换为 java.util.List。然后你可以使用java.util.Collections.sort的一种形式

    Collection< T > collection = ...;
    
    List< T > list = new ArrayList< T >( collection );
    
    Collections.sort( list );
     // or
    Collections.sort( list, new Comparator< T >( ){...} );
    
    // list now is sorted
    

    【讨论】:

    • 虽然这样解决了问题,但这并不是最快的方法,除非集合本身已经是一个List。
    • @Fortega:那么请告诉我什么是对一般集合进行排序同时保留其所有元素的最快方法。顺便说一句,这正是 Google Collections Ordering.sortedCopy 使用的方法。
    • 这取决于集合的类型。对于 toArray() 方法(在 ArrayList 的构造函数中调用)需要迭代所有元素(例如:Set)的集合,排序可能需要对所有元素进行额外的循环。您可以使用允许重复的谷歌集合 TreeMultiset。尽管差异可能不会很大并且处于相同的数量级。
    • 省略号处会发生什么?我有一个Download 类并尝试了Collection&lt;Download&gt; colls = new Collection&lt;Download&gt;(); 并得到一个实例化错误。
    • @gwg - 你不能实例化Collection,它是一个抽象类。但是,您可以将任何扩展集合的内容分配给 Collection 类型的局部变量。
    【解决方案2】:

    如果只有 T,你就不能。它必须由提供者注入:

    Collection<T extends Comparable>
    

    或传入比较器

    Collections.sort(...)
    

    【讨论】:

      【解决方案3】:

      Collection 没有排序,因此想要对其​​进行排序是没有意义的。您可以对List 实例和数组进行排序,这样做的方法是Collections.sort()Arrays.sort()

      【讨论】:

        【解决方案4】:

        java.util.Collections 提供了两个基本选项:

        根据Collection 是什么,您还可以查看SortedSetSortedMap

        【讨论】:

          【解决方案5】:

          假设您有一个 Person 类型的对象列表,使用 Lambda 表达式,您可以通过执行以下操作对用户的姓氏进行排序:

          import java.util.Arrays;
          import java.util.Collections;
          import java.util.Comparator;
          import java.util.List;
          
          class Person {
                  private String firstName;
                  private String lastName;
          
                  public Person(String firstName, String lastName){
                      this.firstName = firstName;
                      this.lastName = lastName;
                  }
          
                  public String getLastName(){
                      return this.lastName;
                  }
          
                  public String getFirstName(){
                      return this.firstName;
                  }
          
                  @Override
                  public String toString(){
                      return "Person: "+ this.getFirstName() + " " + this.getLastName();
                  }
              }
          
              class TestSort {
                  public static void main(String[] args){
                      List<Person> people = Arrays.asList(
                                            new Person("John", "Max"), 
                                            new Person("Coolio", "Doe"), 
                                            new Person("Judith", "Dan")
                      );
          
                      //Making use of lambda expression to sort the collection
                      people.sort((p1, p2)->p1.getLastName().compareTo(p2.getLastName()));
          
                      //Print sorted 
                      printPeople(people);
                  }
          
                  public static void printPeople(List<Person> people){
                      for(Person p : people){
                          System.out.println(p);
                      }
                  }
              }
          

          【讨论】:

            【解决方案6】:

            如果您的集合对象是一个列表,我会使用其他答案中建议的排序方法。

            但是,如果它不是一个列表,并且你并不真正关心返回的是什么类型的 Collection 对象,我认为创建 TreeSet 而不是 List 更快:

            TreeSet sortedSet = new TreeSet(myComparator);
            sortedSet.addAll(myCollectionToBeSorted);
            

            【讨论】:

            • TreeSet 需要 Comparable 才能实现,如果你想对集合进行排序。当我需要一个排序的集合时,我通常会这样做。 TreeSet 也会丢弃重复项。
            • TreeSet 如果使用 Comparator,则不需要实现 Comparable。但是,您对重复项是正确的。
            • OOPS- 错过了坐在那里的比较器。我总是实现 Comparable,所以我完全错过了它。
            • 请注意,只有当集合不包含重复项时,TreeSet 才可行。此外,填充 ArrayList 然后对其进行排序比填充 TreeSet 更快。虽然这两种方法都是 O(N log N),但由于红黑树操作和更大数量的内存分配,TreeSet 具有更高的常数因子。尽管如此,我有时还是使用 TreeSet 来使我的代码更简洁,尽管这比使用 ArrayList 慢。
            【解决方案7】:

            这是一个例子。 (为方便起见,我使用 Apache 的 CompareToBuilder 类,虽然这可以不使用它来完成。)

            import java.util.ArrayList;
            import java.util.Calendar;
            import java.util.Collections;
            import java.util.Comparator;
            import java.util.Date;
            import java.util.HashMap;
            import java.util.List;
            import org.apache.commons.lang.builder.CompareToBuilder;
            
            public class Tester {
                boolean ascending = true;
            
                public static void main(String args[]) {
                    Tester tester = new Tester();
                    tester.printValues();
                }
            
                public void printValues() {
                    List<HashMap<String, Object>> list =
                        new ArrayList<HashMap<String, Object>>();
                    HashMap<String, Object> map =
                        new HashMap<String, Object>();
            
                    map.put( "actionId", new Integer(1234) );
                    map.put( "eventId",  new Integer(21)   );
                    map.put( "fromDate", getDate(1)        );
                    map.put( "toDate",   getDate(7)        );
                    list.add(map);
            
                    map = new HashMap<String, Object>();
                    map.put( "actionId", new Integer(456) );
                    map.put( "eventId",  new Integer(11)  );
                    map.put( "fromDate", getDate(1)       );
                    map.put( "toDate",   getDate(1)       );
                    list.add(map);
            
                    map = new HashMap<String, Object>();
                    map.put( "actionId", new Integer(1234) );
                    map.put( "eventId",  new Integer(20)   );
                    map.put( "fromDate", getDate(4)        );
                    map.put( "toDate",   getDate(16)       );
                    list.add(map);
            
                    map = new HashMap<String, Object>();
                    map.put( "actionId", new Integer(1234) );
                    map.put( "eventId",  new Integer(22)   );
                    map.put( "fromDate", getDate(8)        );
                    map.put( "toDate",   getDate(11)       );
                    list.add(map);
            
            
                    map = new HashMap<String, Object>();
                    map.put( "actionId", new Integer(1234) );
                    map.put( "eventId",  new Integer(11)   );
                    map.put( "fromDate", getDate(1)        );
                    map.put( "toDate",   getDate(10)       );
                    list.add(map);
            
                    map = new HashMap<String, Object>();
                    map.put( "actionId", new Integer(1234) );
                    map.put( "eventId",  new Integer(11)   );
                    map.put( "fromDate", getDate(4)        );
                    map.put( "toDate",   getDate(15)       );
                    list.add(map);
            
                    map = new HashMap<String, Object>();
                    map.put( "actionId", new Integer(567) );
                    map.put( "eventId",  new Integer(12)  );
                    map.put( "fromDate", getDate(-1)      );
                    map.put( "toDate",   getDate(1)       );
                    list.add(map);
            
                    System.out.println("\n Before Sorting \n ");
                    for( int j = 0; j < list.size(); j++ )
                        System.out.println(list.get(j));
            
                    Collections.sort( list, new HashMapComparator2() );
            
                    System.out.println("\n After Sorting \n ");
                    for( int j = 0; j < list.size(); j++ )
                        System.out.println(list.get(j));
                }
            
                public static Date getDate(int days) {
                    Calendar cal = Calendar.getInstance();
                    cal.setTime(new Date());
                    cal.add(Calendar.DATE, days);
                    return cal.getTime();
                }
            
                public class HashMapComparator2 implements Comparator {
                    public int compare(Object object1, Object object2) {
                        if( ascending ) {
                            return new CompareToBuilder()
                                .append(
                                    ((HashMap)object1).get("actionId"),
                                    ((HashMap)object2).get("actionId")
                                )
                                .append(
                                    ((HashMap)object2).get("eventId"),
                                    ((HashMap)object1).get("eventId")
                                )
                            .toComparison();
                        } else {
                            return new CompareToBuilder()
                                .append(
                                    ((HashMap)object2).get("actionId"),
                                    ((HashMap)object1).get("actionId")
                                )
                                .append(
                                    ((HashMap)object2).get("eventId"),
                                    ((HashMap)object1).get("eventId")
                                )
                            .toComparison();
                        }
                    }
                }
            }
            

            如果您正在处理特定代码并且遇到问题,您可以发布您的伪代码,我们可以尝试帮助您!

            【讨论】:

            • 谢谢你的回复,但我有一个通用的集合,这个例子不适合我
            【解决方案8】:

            我遇到了类似的问题。必须对 3rd 方类(对象)列表进行排序。

            List<ThirdPartyClass> tpc = getTpcList(...);
            

            ThirdPartyClass 没有实现 Java Comparable 接口。我从mkyong 找到了一个关于如何解决这个问题的优秀插图。我不得不使用 Comparator 方法进行排序。

            //Sort ThirdPartyClass based on the value of some attribute/function
            Collections.sort(tpc, Compare3rdPartyObjects.tpcComp);
            

            比较器在哪里:

            public abstract class Compare3rdPartyObjects {
            
            public static Comparator<ThirdPartyClass> tpcComp = new Comparator<ThirdPartyClass>() {
            
                public int compare(ThirdPartyClass tpc1, ThirdPartyClass tpc2) {
            
                    Integer tpc1Offset = compareUsing(tpc1);
                    Integer tpc2Offset = compareUsing(tpc2);
            
                    //ascending order
                    return tpc1Offset.compareTo(tpc2Offset);
            
                }
            };
            
            //Fetch the attribute value that you would like to use to compare the ThirdPartyClass instances 
            public static Integer compareUsing(ThirdPartyClass tpc) {
            
                Integer value = tpc.getValueUsingSomeFunction();
                return value;
            }
            }
            

            【讨论】:

              猜你喜欢
              • 2017-02-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-05-03
              • 1970-01-01
              • 1970-01-01
              • 2019-12-13
              相关资源
              最近更新 更多