关于排序:为什么Java中没有SortedList?

Why is there no SortedList in Java?

在Java中,有EDOCX1×0和EDCOX1,1个接口。它们都属于Java的标准集合框架,并提供了一种排序的访问元素的方法。

然而,在我的理解中,Java中没有EDCOX1 2Ω。您可以使用java.util.Collections.sort()对列表进行排序。

你知道为什么要这样设计吗?


列表迭代器首先保证按照列表的内部顺序(aka)获取列表的元素。插入顺序)。更具体地说,它是按照插入元素的顺序,或者按照操作列表的方式。排序可以看作是对数据结构的操作,有几种方法可以对列表进行排序。好的。

我会按照我个人认为的有用性的顺序来排序:好的。1。考虑改用SetBag集合。

注意:我把这个选项放在最上面,因为这是你通常想要做的。好的。

排序集在插入时自动对集合排序,这意味着它在向集合中添加元素时进行排序。它还意味着不需要手动排序。好的。

此外,如果您确定不需要担心(或拥有)重复的元素,那么您可以使用TreeSet。它实现了SortedSetNavigableSet接口,并且可以像您从列表中可能期望的那样工作:好的。

1
2
3
4
5
6
7
8
9
TreeSet<String> set = new TreeSet<String>();
set.add("lol");
set.add("cat");
// automatically sorts natural order when adding

for (String s : set) {
    System.out.println(s);
}
// Prints out"cat" and"lol"

如果不需要自然排序,可以使用接受Comparator的构造函数参数。好的。

或者,您可以使用多集(也称为包),即允许重复元素的Set,而有第三方实现。最值得注意的是,在guava图书馆有一个TreeMultiset,它的工作原理与TreeSet非常相似。好的。2。用Collections.sort()排序

如上所述,Lists的排序是对数据结构的操作。因此,对于需要"一个真相来源"的情况,将以各种方式进行排序,然后手动对其进行排序是可行的。好的。

您可以使用java.util.Collections.sort()方法对列表进行排序。下面是一个关于如何:好的。

1
2
3
4
5
6
7
8
9
List<String> strings = new ArrayList<String>()
strings.add("lol");
strings.add("cat");

Collections.sort(strings);
for (String s : strings) {
    System.out.println(s);
}
// Prints out"cat" and"lol"

使用比较器

一个明显的好处是,您可以在sort方法中使用Comparator。Java还为EDOCX1 12提供了一些实现,例如EDCOX1 OR 15),这对于区域敏感的排序字符串是有用的。下面是一个例子:好的。

1
2
3
4
Collator usCollator = Collator.getInstance(Locale.US);
usCollator.setStrength(Collator.PRIMARY); // ignores casing

Collections.sort(strings, usCollator);

并行环境中的排序

尽管使用sort方法在并发环境中不友好,但请注意,因为集合实例将被操作,您应该考虑使用不可变的集合。这是guava在Ordering类中提供的,是一个简单的一行程序:好的。

1
List<string> sorted = Ordering.natural().sortedCopy(strings);

三。用java.util.PriorityQueue把你的清单包起来

虽然Java中没有排序列表,但是有一个排序的队列,这可能对你也同样有效。它是java.util.PriorityQueue类。好的。

NicoHaase在评论中提到了一个相关问题,也回答了这个问题。好的。

在已排序的集合中,您很可能不希望操作内部数据结构,这就是PriorityQueue不实现列表接口的原因(因为这样可以直接访问其元素)。好的。关于PriorityQueue迭代器的警告

PriorityQueue类实现了IterableCollection接口,因此可以像往常一样迭代。但是,迭代器不能保证按排序顺序返回元素。相反(正如Alderah在评论中指出的那样),您需要删除队列直到清空。好的。

请注意,可以通过接受任何集合的构造函数将列表转换为优先级队列:好的。

1
2
3
4
5
6
7
8
9
List<String> strings = new ArrayList<String>()
strings.add("lol");
strings.add("cat");

PriorityQueue<String> sortedStrings = new PriorityQueue(strings);
while(!sortedStrings.isEmpty()) {
    System.out.println(sortedStrings.poll());
}
// Prints out"cat" and"lol"

4。写你自己的SortedList

注意:你不应该这样做。好的。

您可以编写自己的列表类,在每次添加新元素时对其进行排序。这可能会使计算变得相当繁重,这取决于您的实现,而且是毫无意义的,除非您希望将其作为练习来进行,因为有两个主要原因:好的。

  • 它破坏了List接口所具有的契约,因为add方法应确保元素将驻留在用户指定的索引中。
  • 为什么要重新发明轮子?您应该使用treeset或multisets,而不是上面第一点中指出的。
  • 但是,如果您想将它作为一个练习,这里有一个代码示例来帮助您开始,它使用AbstractList抽象类:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class SortedList<E> extends AbstractList<E> {

        private ArrayList<E> internalList = new ArrayList<E>();

        // Note that add(E e) in AbstractList is calling this one
        @Override
        public void add(int position, E e) {
            internalList.add(e);
            Collections.sort(internalList, null);
        }

        @Override
        public E get(int i) {
            return internalList.get(i);
        }

        @Override
        public int size() {
            return internalList.size();
        }

    }

    请注意,如果您没有重写所需的方法,那么来自AbstractList的默认实现将抛出UnsupportedOperationException。好的。好啊。


    因为列表的概念与自动排序集合的概念不兼容。列表的要点是,在调用list.add(7, elem)之后,调用list.get(7)将返回elem。使用自动排序的列表,元素可能会以任意位置结束。


    由于所有列表都已按添加项目的顺序"排序"(FIFO排序),因此可以使用java.util.Collections.sort()使用其他顺序"替换"列表,包括元素的自然排序。

    编辑:

    作为数据结构的列表基于有趣的是插入项的顺序。

    集合没有该信息。

    如果您想通过增加时间来订购,请使用List。如果您想按其他标准订购,请使用SortedSet


    集合和映射是非线性数据结构。列表是线性数据结构。

    enter image description here

    树数据结构SortedSetSortedMap接口分别使用红黑树实现算法实现TreeSetTreeMap。因此,它确保没有重复的项目(或在Map的情况下的键)。

    • List已经维护了有序的收集和基于索引的数据结构,树不是基于索引的数据结构。
    • 根据定义,Tree不能包含重复项。
    • List中,我们可以有副本,因此没有TreeList(即没有SortedList)。
    • 列表按插入顺序维护元素。因此,如果我们想对列表进行排序,就必须使用java.util.Collections.sort()。它根据元素的自然顺序,将指定的列表按升序排序。

    对于任何新来者,截至2015年4月,Android现在在支持库中有一个SortedList类,专门设计用于与RecyclerView合作。这是关于它的博客文章。


    Javafx SortedList

    虽然花了一段时间,Java 8确实有一个排序的EDCOX1×1。http://docs.oracle.com/javase/8/javafx/api/javafx/collections/transformation/sortedlist.html

    正如您在javadocs中看到的,它是javafx集合的一部分,旨在提供一个可观察列表上的排序视图。

    更新:注意,在Java 11中,JavaFX工具包已经移动到JDK之外,现在是一个单独的库。JavaFX11可以作为可下载的SDK或Mavenentral提供。请参阅https://openjfx.io


    另一点是插入操作的时间复杂性。对于列表插入,我们期望其复杂性为O(1)。但这不能用排序列表来保证。

    最重要的一点是列表对它们的元素没有任何假设。例如,您可以列出不实现equalscompare的内容。


    这样想:List接口有add(int index, E element)set(int index, E element)这样的方法。约定是,一旦在位置x添加了一个元素,除非在元素之前添加或删除元素,否则将在此处找到它。

    如果任何列表实现将以某种顺序(而不是基于索引)存储元素,则上述列表方法将毫无意义。


    列表API中的第一行表示它是一个有序集合(也称为序列)。如果对列表排序,则无法维护该顺序,因此Java中没有树列表。正如API所说,Java列表从序列中得到启发,并看到序列属性http://e.维基百科org/wiki /序列(数学)。

    这并不意味着你不能对列表进行排序,但Java严格按照他的定义,默认情况下不提供排序列表的版本。


    考虑使用索引树映射。它是一个增强的JDK树集,通过索引提供对元素的访问,并且不需要迭代或隐藏的支持树的底层列表就可以找到元素的索引。该算法基于每次发生变化时更新变化节点的权重。