列表迭代器首先确保您以列表的内部顺序(也称为插入顺序)获取列表的元素。更具体地说,它是按照插入元素的顺序或操作列表的方式进行的。排序可以看作是对数据结构的一种操作,有几种方法可以对列表进行排序。
我将按照自己的见解按实用性的顺序进行排序:
1.考虑改用Set
或Bag
集合
注意:我将此选项放在顶部,因为这通常是您通常要执行的操作。
排序集会在插入时自动对集合进行排序,这意味着在您将元素添加到集合时会进行排序。这也意味着您无需手动对其进行排序。
此外,如果您确定不必担心(或拥有)重复的元素,则可以使用TreeSet<T>
代替。它实现SortedSet
和NavigableSet
接口并按照您可能希望从列表中进行的方式工作:
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<T>
。
或者,您可以使用Multisets(也称为Bags),它是Set
允许重复元素的,并且存在它们的第三方实现。最明显的是在Guava库中有一个TreeMultiset
,它的工作方式类似于TreeSet
。
2.用 Collections.sort()
如上所述,对List
s进行排序是对数据结构的一种操作。因此,对于需要以多种方式进行分类的“一个真理源”的情况,则必须手动进行分类。
您可以使用该java.util.Collections.sort()
方法对列表进行排序。这是有关如何的代码示例:
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"
使用比较器
一个明显的好处是您可以Comparator
在该sort
方法中使用。Java还为提供了一些实现,Comparator
例如,Collator
对于对语言环境敏感的排序字符串很有用。这是一个例子:
Collator usCollator = Collator.getInstance(Locale.US);
usCollator.setStrength(Collator.PRIMARY); // ignores casing
Collections.sort(strings, usCollator);
在并发环境中排序
请注意,尽管sort
在并发环境中使用该方法并不友好,因为将操作集合实例,因此您应考虑使用不可变的集合。这是Guava在Ordering
课堂上提供的东西,并且很简单:
List<string> sorted = Ordering.natural().sortedCopy(strings);
3.用 java.util.PriorityQueue
尽管Java中没有排序列表,但是有一个排序队列可能对您同样有效。这是java.util.PriorityQueue
上课。
Nico Haase在评论中链接到一个相关问题,该问题也得到了回答。
在排序的集合中,您很可能不想操纵内部数据结构,这就是为什么PriorityQueue不实现List接口的原因(因为这将使您直接访问其元素)。
警告PriorityQueue
迭代器
在PriorityQueue
类实现Iterable<E>
和Collection<E>
接口,因此它可以重复如常。但是,不能保证迭代器以已排序的顺序返回元素。而是(如Alderath在评论中指出的那样)您需要poll()
排队直到空着。
请注意,您可以通过采用任何集合的构造函数将列表转换为优先级队列:
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类,该类在每次添加新元素时进行排序。取决于您的实现,这可能会使计算工作变得繁重,并且毫无意义,除非您希望将其作为练习,这有两个主要原因:
- 它破坏了
List<E>
接口所具有的约定,因为add
方法应确保该元素将驻留在用户指定的索引中。
- 为什么要重新发明轮子?如上第一点所指出的,您应该使用TreeSet或Multisets。
但是,如果您想作为练习来做,这里是一个入门的代码示例,它使用AbstractList
抽象类:
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();
}
}
请注意,如果您没有重写所需的方法,则from的默认实现AbstractList
将抛出UnsupportedOperationException
。