在Java中,有EDOCX1×0和EDCOX1,1个接口。它们都属于Java的标准集合框架,并提供了一种排序的访问元素的方法。
然而,在我的理解中,Java中没有EDCOX1 2Ω。您可以使用java.util.Collections.sort()对列表进行排序。
你知道为什么要这样设计吗?
- stackoverflow.com/questions/416266/sorted-collection-in-java有帮助吗?
- 那么,在列表中间插入元素时,预期的结果是什么呢?
- @最好有一个SortedList类,它不实现java.util.list接口。把这个问题理解为一个疑问,为什么没有支持所请求功能的数据结构。不要被一些无关紧要的细节如命名分散注意力。
- @Alderah,通常的结构是一个树(红/黑,avl或btree),带有额外的prev/next链接来支持排序。我确实使用了类似的结构,红色/黑色,带上一个/下一个链接。不过,这是一个相当利基的用途。树可以按顺序和插入顺序遍历,有O(logn)find/contains,但get(int)是O(n)。考虑到它的利基适用性,我认为如果开发人员需要的话,应该由他们来实现它。
- 不回答"为什么"这个问题,但TreeSet最简单的解决方法是使用一个从不返回零的比较器,例如int diff = this.score - that.score;return (diff == 0) ? 1 : diff;,因为它是一个臭烘烘的黑客程序,我将把它作为一个匿名的构造函数参数提供,而不是让任何可比的实现。
列表迭代器首先保证按照列表的内部顺序(aka)获取列表的元素。插入顺序)。更具体地说,它是按照插入元素的顺序,或者按照操作列表的方式。排序可以看作是对数据结构的操作,有几种方法可以对列表进行排序。好的。
我会按照我个人认为的有用性的顺序来排序:好的。1。考虑改用Set或Bag集合。
注意:我把这个选项放在最上面,因为这是你通常想要做的。好的。
排序集在插入时自动对集合排序,这意味着它在向集合中添加元素时进行排序。它还意味着不需要手动排序。好的。
此外,如果您确定不需要担心(或拥有)重复的元素,那么您可以使用TreeSet。它实现了SortedSet和NavigableSet接口,并且可以像您从列表中可能期望的那样工作:好的。
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),这对于区域敏感的排序字符串是有用的。下面是一个例子:好的。
并行环境中的排序
尽管使用sort方法在并发环境中不友好,但请注意,因为集合实例将被操作,您应该考虑使用不可变的集合。这是guava在Ordering类中提供的,是一个简单的一行程序:好的。
1
| List<string> sorted = Ordering.natural().sortedCopy(strings); |
三。用java.util.PriorityQueue把你的清单包起来
虽然Java中没有排序列表,但是有一个排序的队列,这可能对你也同样有效。它是java.util.PriorityQueue类。好的。
NicoHaase在评论中提到了一个相关问题,也回答了这个问题。好的。
在已排序的集合中,您很可能不希望操作内部数据结构,这就是PriorityQueue不实现列表接口的原因(因为这样可以直接访问其元素)。好的。关于PriorityQueue迭代器的警告
PriorityQueue类实现了Iterable和Collection接口,因此可以像往常一样迭代。但是,迭代器不能保证按排序顺序返回元素。相反(正如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。好的。好啊。
- + 1。在我看来,这比最高投票的答案更有建设性。不过,它有两个小缺点。PriorityQueue不支持随机访问。不能查看(elementindex)。所以你不能这样做,比如Integer maxVal = prioQueue.peek(prioQueue.size() - 1);。其次,如果您打算将PriorityQueue简单地用作排序列表,那么在代码中看到PriorityQueue的感觉就不如在存在这样的数据结构的情况下看到SortedList的感觉那么直观。
- 而且,在研究了其他一些人在注释中链接的问题之后,另一个很大的缺点是PriorityQueue的迭代器不能保证以任何特定的顺序返回元素。所以,除非我忽略了一些东西,否则打印priorityqueue中所有对象的唯一方法就是重复poll()队列,直到队列为空。对我来说,这感觉是重新开始的边界线。要在PriorityQueue中打印两次对象,首先必须复制PriorityQueue,然后pol l()原始PriorityQueue中的所有对象,然后pol()l复制中的所有对象。
- 隐马尔可夫模型。。。看起来你是对的,阿尔德拉蒂。不能使用PriorityQueue的迭代器按预期顺序获取元素。看起来我必须编辑我的答案。
- 排序列表是通过树实现的,否则太昂贵了
- 优先级队列只是一个堆,您只能访问顶部,IMO它不属于问题的答案。
- 另外值得注意的是,Collections.sort()甚至允许您使用Comparator对象定义用于排序的比较函数。
- 我认为需要某种分类的索引集合。我正在开发一个应用程序,我需要一个可以通过索引号访问的数据收集,但是要保持一个非常具体的顺序。我不想一直使用sort()或comparator。所以,是的,我可能要创建一个自定义集合,它只是从集合继承,而不是从列表继承,来实现这个函数。
- treemultiset以一种非常奇怪的方式允许多重运算。如果有两个对象具有相同的键,而不是将所有对象实际插入多集,那么它只跟踪与该键匹配的计数。如果您使用的是原语,这是可以的。但是,如果您正在使用对象,并且计划使用对象的其他部分,那么它将不会返回预期的对象。
- @spoike`因为add方法应该确保元素将驻留在用户指定的索引中`实际上,它在末尾添加,您可以使用put()在映射中指定索引。我迷惑了吗?
- @juanmf-Map的键(或索引)与List的索引不同。使用put()无法确保当您迭代映射的entryset时(即,除非您按键对entryset进行排序),将某个值放入较低的数字中,将某个值放入较高的数字中。
- 所有这些建议的一个巨大缺点是,sourtedmap和sortedset提供的.sub*功能缺失,而且至少在我的经验中,这是最需要的功能。
因为列表的概念与自动排序集合的概念不兼容。列表的要点是,在调用list.add(7, elem)之后,调用list.get(7)将返回elem。使用自动排序的列表,元素可能会以任意位置结束。
由于所有列表都已按添加项目的顺序"排序"(FIFO排序),因此可以使用java.util.Collections.sort()使用其他顺序"替换"列表,包括元素的自然排序。
编辑:
作为数据结构的列表基于有趣的是插入项的顺序。
集合没有该信息。
如果您想通过增加时间来订购,请使用List。如果您想按其他标准订购,请使用SortedSet。
- 集合不允许重复
- 我认为这不是一个很好的答案。当然,JavaAPI中的列表确实有一个特定的排序,这些顺序是由插入项目的时间/方式决定的。然而,以依赖于插入方法/时间的方式排序的列表的存在并不妨碍具有其他数据结构,其中顺序是以其他方式确定的(例如,通过比较器)。基本上,操作人员会问,为什么没有一个与排序集等效的数据结构,但数据结构应该允许出现多个相等的元素。
- 所以我接下来的问题是:"为什么没有像排序集那样工作的数据结构,但它可以包含多个相等的元素?"(请不要回答"因为集合只能包含一个元素")。
- @Alderah:请参见stackoverflow.com/questions/416266/sorted-collection-in-java。简而言之:使用番石榴的Treemultiset
- 我认为lists are already sorted by its order这个句子有点误导人。是的,Lists有一个默认的fifo顺序(添加项目的顺序),但是读到这句话,我在考虑元素的自然顺序,这有点不同。我提议修改一下
- 列表不会"排序",即使您将"排序"放在双引号中。他们被命令了。
集合和映射是非线性数据结构。列表是线性数据结构。
树数据结构SortedSet和SortedMap接口分别使用红黑树实现算法实现TreeSet和TreeMap。因此,它确保没有重复的项目(或在Map的情况下的键)。
- List已经维护了有序的收集和基于索引的数据结构,树不是基于索引的数据结构。
- 根据定义,Tree不能包含重复项。
- 在List中,我们可以有副本,因此没有TreeList(即没有SortedList)。
- 列表按插入顺序维护元素。因此,如果我们想对列表进行排序,就必须使用java.util.Collections.sort()。它根据元素的自然顺序,将指定的列表按升序排序。
对于任何新来者,截至2015年4月,Android现在在支持库中有一个SortedList类,专门设计用于与RecyclerView合作。这是关于它的博客文章。
- 值得注意的是,在注释时,AndroidsSortedList缺少对RecyclerView的OnitemMoved()功能的支持。写我自己的排序表,这是效率较低的是我必须做的,以摆脱限制。
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
- 不幸的是,这个sortedList不像一个普通的列表那样工作-例如,它没有一个默认的构造函数(您必须使用一个ObservableList来构造它,不管这意味着什么…)
- JavaFX中的SortedList显然是用于使用GUI组件的,因为其开销不适合仅拥有排序对象的列表。此外,它还意味着引用整个Fx模块,即使项目中没有使用GUI。
- @眼镜蛇。是的,没错。一个性能更高的排序列表可能是一个围绕树映射的薄包装器,其中一个整数用于计算键的重复项。您也可以使用带有从不返回0的比较器的treeset。
- 为什么投反对票?这个问题首先假定JDK库中没有排序列表。这个答案纠正了这个假设。不管您喜欢还是不喜欢这个特定排序列表的实现,都不是拒绝投票的原因。这个答案并不推荐这个类,只是指出它的存在。
另一点是插入操作的时间复杂性。对于列表插入,我们期望其复杂性为O(1)。但这不能用排序列表来保证。
最重要的一点是列表对它们的元素没有任何假设。例如,您可以列出不实现equals或compare的内容。
- 您可以让list w/o(logn)insert/delete/find/contains,但不允许w/get(int)。
- 最后一点不是很好的解释。您可以将不实现Comparable的东西制作成SortedSet。请参见此TreeSet构造函数。
- @可能我的措词太弱了。然而,观察认为,集合元素和树键元素必须至少在相等性方面具有可比性,而列表元素则不需要。无论集合和树的排序/相等关系是在比较器中实现还是在其他地方实现都是无关紧要的——但您需要一个。
- 列表不保证o(1)插入,它们保证o(1)访问。Bigocheatsheet.com网站
- @马奎格利是吗?对于链表,list.get(5)不在o(1)中。
- @你说得对!我不能更新我的注释,但是Java EDCOX1 1接口不能保证其方法的任何性能规范。
这样想:List接口有add(int index, E element)和set(int index, E element)这样的方法。约定是,一旦在位置x添加了一个元素,除非在元素之前添加或删除元素,否则将在此处找到它。
如果任何列表实现将以某种顺序(而不是基于索引)存储元素,则上述列表方法将毫无意义。
列表API中的第一行表示它是一个有序集合(也称为序列)。如果对列表排序,则无法维护该顺序,因此Java中没有树列表。正如API所说,Java列表从序列中得到启发,并看到序列属性http://e.维基百科org/wiki /序列(数学)。
这并不意味着你不能对列表进行排序,但Java严格按照他的定义,默认情况下不提供排序列表的版本。
- commons.apache.org/proper/commons collections/apidocs/org/&hellip;
考虑使用索引树映射。它是一个增强的JDK树集,通过索引提供对元素的访问,并且不需要迭代或隐藏的支持树的底层列表就可以找到元素的索引。该算法基于每次发生变化时更新变化节点的权重。