Java中的排序集合

时间:2009-01-06 12:02:06

标签: java sorting collections

我是Java的初学者。请建议可以/应该使用哪些集合来维护Java中的排序列表。我尝试了MapSet,但他们并不是我想要的。

20 个答案:

答案 0 :(得分:182)

这很晚,但是JDK中有一个类只是为了有一个排序列表。它被命名(与其他Sorted*接口有点不正常)“java.util.PriorityQueue”。它可以对Comparable<?>进行排序,也可以使用Comparator

使用List排序的Collections.sort(...)的差异在于,通过使用堆数据结构,它将始终保持部分顺序,具有O(log(n))插入性能,而在排序的ArrayList中插入将是O(n)(即,使用二进制搜索和移动)。

但是,与List不同,PriorityQueue不支持索引访问(get(5)),访问堆中项目的唯一方法是将其取出,一次(因此名称为PriorityQueue)。

答案 1 :(得分:53)

TreeMap和TreeSet将按排序顺序对内容进行迭代。或者您可以使用ArrayList并使用Collections.sort()对其进行排序。所有这些类都在java.util

答案 2 :(得分:32)

如果您想维护排序列表,您将经常修改(即除了排序之外,还允许重复且其元素可以有效的结构由index引用,然后使用ArrayList,但是当您需要插入元素时,请始终使用 Collections.binarySearch()来确定添加给定元素的索引。后一种方法告诉您需要插入的索引,以使列表保持排序顺序。

答案 3 :(得分:31)

使用Google Guava的TreeMultiset课程。 Guava有一个壮观的集合API。

提供维护排序顺序的List实现的一个问题是add()方法的JavaDocs中的承诺。

答案 4 :(得分:12)

您需要SortedSet实施,即TreeSet

答案 5 :(得分:12)

有几个选择。如果你不想要重复,我建议使用TreeSet,你插入的对象是可比较的。

您还可以使用Collections类的静态方法执行此操作。

有关详细信息,请参阅Collections#sort(java.util.List)TreeSet

答案 6 :(得分:9)

如果您只想对列表进行排序,请使用任何类型的List并使用Collections.sort()。如果要确保列表中的元素是唯一的并且始终排序,请使用SortedSet

答案 7 :(得分:5)

我所做的是实现具有委托所有方法的内部实例的List。

 public class ContactList implements List<Contact>, Serializable {
    private static final long serialVersionUID = -1862666454644475565L;
    private final List<Contact> list;

public ContactList() {
    super();
    this.list = new ArrayList<Contact>();
}

public ContactList(List<Contact> list) {
    super();
    //copy and order list
    List<Contact>aux= new ArrayList(list);
    Collections.sort(aux);

    this.list = aux;
}

public void clear() {
    list.clear();
}

public boolean contains(Object object) {
    return list.contains(object);
}

之后,我实现了一个新方法“putOrdered”,如果该元素不存在则插入到正确的位置,或者仅在它存在的情况下替换。

public void putOrdered(Contact contact) {
    int index=Collections.binarySearch(this.list,contact);
    if(index<0){
        index= -(index+1);
        list.add(index, contact);
    }else{
        list.set(index, contact);
    }
}

如果你想允许重复元素,只需实现addOrdered(或两者)。

public void addOrdered(Contact contact) {
    int index=Collections.binarySearch(this.list,contact);
    if(index<0){
        index= -(index+1);
    }
    list.add(index, contact);
}

如果要避免插入,还可以在“add”和“set”方法上抛出和不支持的操作异常。

public boolean add(Contact object) {
    throw new UnsupportedOperationException("Use putOrdered instead");
}

...而且你必须小心ListIterator方法,因为他们可以修改你的内部列表。在这种情况下,您可以返回内部列表的副本或再次抛出异常。

public ListIterator<Contact> listIterator() {
    return (new ArrayList<Contact>(list)).listIterator();
}

答案 8 :(得分:4)

使用LambdaJ

如果您使用的是Java 8的先前版本,可以尝试使用 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());
        }
}); 

按LambdaJ排序

List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge()); 

当然,拥有这种美感会影响性能(平均2次),但你能找到更易读的代码吗?

使用lambda表达式

对java 8进行排序
Collections.sort(persons, (p1, p2) -> p1.getAge().compareTo(p2.getAge()));
//or
persons.sort((p1, p2) -> p1.getAge().compareTo(p2.getAge()));

答案 9 :(得分:4)

实现您想要的排序列表的最有效方法是实现可索引的跳过列表,如下所示:Wikipedia: Indexable skiplist。 它允许在O(log(n))中插入/删除,并允许同时具有索引访问。它也会允许重复。

跳过清单非常有趣,我想说,它被低估了数据结构。 遗憾的是,Java库中没有索引跳过列表实现,但您可以使用其中一个开源实现或自己实现。有常规的跳过列表实现,如ConcurrentSkipListSetConcurrentSkipListMap

答案 10 :(得分:4)

TreeSet不起作用,因为它们不允许重复,而且它们不提供在特定位置获取元素的方法。 PriorityQueue不起作用,因为它不允许在特定位置获取元素,这是列表的基本要求。 我认为您需要实现自己的算法来维护带有O(logn)插入时间的Java中的排序列表,除非您不需要重复项。 也许解决方案可能是使用TreeMap,其中键是覆盖equals方法的项的子类,以便允许重复。

答案 11 :(得分:2)

PriorityQueue的问题在于它由一个简单的数组支持,并且按顺序获取元素的逻辑由“queue [2 * n + 1]和queue [2 *(n + 1)]完成“东西。如果你只是从头部拉出来它会很有效,但是如果你试图在某个时候调用.toArray,它会变得无用。

我通过使用com.google.common.collect.TreeMultimap解决了这个问题,但是我提供了一个自定义的Comparator,它包含在Ordering中,永远不会返回0.

离。 for Double:

private static final Ordering<Double> NoEqualOrder = Ordering.from(new Comparator<Double>() {

    @Override
    public int compare(Double d1, Double d2)
    {
        if (d1 < d2) {
            return -1;
        }
        else {
            return 1;
        }
    }
});

这样,当我调用.toArray()时,我按顺序获取值,并且还有重复项。

答案 12 :(得分:1)

你想要的是二叉搜索树。它维护排序顺序,同时提供搜索,删除和插入的对数访问(除非你有一个退化树 - 然后它是线性的)。它很容易实现,甚至可以使它实现List接口,但是索引访问变得复杂。

第二种方法是使用ArrayList,然后使用冒泡排序实现。由于您一次插入或删除一个元素,因此插入和删除的访问时间是线性的。搜索是对数和索引访问常量(LinkedList的时间可以不同)。您需要的唯一代码是5个,可能是6行冒泡排序。

答案 13 :(得分:1)

您可以使用Arraylist和Treemap,正如您所说,您想要重复的值,然后您不能使用TreeSet,尽管它也已经排序,但您必须定义比较器。

答案 14 :(得分:1)

对于Set,您可以使用TreeSet。 TreeSet根据自然顺序或传递给该特定对象的Comparable的任何排序顺序对元素进行排序。 对于地图,请使用TreeMap。 TreeMap提供了对键的排序。为了将对象添加为TreeMap的键,该类应实现可比较的接口,从而强制实现包含排序顺序定义的compare to()方法。 http://techmastertutorial.in/java-collection-impl.html

答案 15 :(得分:0)

使用sort()方法对列表进行排序,如下所示:

List list = new ArrayList();

//add elements to the list

Comparator comparator = new SomeComparator();

Collections.sort(list, comparator);

供参考,请参阅链接: https://www.quora.com/How-does-Facebook-know-what-I-looked-at-on-Amazon

答案 16 :(得分:0)

使用TreeSet以排序顺序提供元素。或使用Collection.sort()Comparator()进行外部排序。

答案 17 :(得分:0)

import java.util.TreeSet;

public class Ass3 {
    TreeSet<String>str=new TreeSet<String>();
    str.add("dog");
    str.add("doonkey");
    str.add("rat");
    str.add("rabbit");
    str.add("elephant");
    System.out.println(str);    
}

答案 18 :(得分:0)

使用Java 8 Comparator,如果我们要对列表进行排序,那么这是世界上人口最多的10个城市,我们希望按名称对它进行排序(如Time所报道)。      日本大阪。墨西哥墨西哥城。 ...        中国北京。 ……巴西圣保罗。 ……印度孟买。 ...上海        中国。 ……印度德里。 ...日本东京。

 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;

public class SortCityList {

    /*
     * Here are the 10 most populated cities in the world and we want to sort it by
     * name, as reported by Time. Osaka, Japan. ... Mexico City, Mexico. ...
     * Beijing, China. ... São Paulo, Brazil. ... Mumbai, India. ... Shanghai,
     * China. ... Delhi, India. ... Tokyo, Japan.
     */
    public static void main(String[] args) {
        List<String> cities = Arrays.asList("Osaka", "Mexico City", "São Paulo", "Mumbai", "Shanghai", "Delhi",
                "Tokyo");
        System.out.println("Before Sorting List is:-");
        System.out.println(cities);
        System.out.println("--------------------------------");

        System.out.println("After Use of List sort(String.CASE_INSENSITIVE_ORDER) & Sorting List is:-");
        cities.sort(String.CASE_INSENSITIVE_ORDER);
        System.out.println(cities);
        System.out.println("--------------------------------");
        System.out.println("After Use of List sort(Comparator.naturalOrder()) & Sorting List is:-");
        cities.sort(Comparator.naturalOrder());
        System.out.println(cities);

    }

}

答案 19 :(得分:0)

根据用户定义的标准对ArrayList进行排序。

模型类

 class Student 
 { 
     int rollno; 
     String name, address; 

     public Student(int rollno, String name, String address) 
     { 
         this.rollno = rollno; 
         this.name = name; 
         this.address = address; 
     }   

     public String toString() 
     { 
         return this.rollno + " " + this.name + " " + this.address; 
     } 
 } 

排序类别

 class Sortbyroll implements Comparator<Student> 
 {         
     public int compare(Student a, Student b) 
     { 
         return a.rollno - b.rollno; 
     } 
 } 

主类

 class Main 
 { 
     public static void main (String[] args) 
     { 
         ArrayList<Student> ar = new ArrayList<Student>(); 
         ar.add(new Student(111, "bbbb", "london")); 
         ar.add(new Student(131, "aaaa", "nyc")); 
         ar.add(new Student(121, "cccc", "jaipur")); 

         System.out.println("Unsorted"); 
         for (int i=0; i<ar.size(); i++) 
             System.out.println(ar.get(i)); 

         Collections.sort(ar, new Sortbyroll()); 

         System.out.println("\nSorted by rollno"); 
         for (int i=0; i<ar.size(); i++) 
             System.out.println(ar.get(i)); 
     } 
 } 

输出

 Unsorted
 111 bbbb london
 131 aaaa nyc
 121 cccc jaipur

 Sorted by rollno
 111 bbbb london
 121 cccc jaipur
 131 aaaa nyc