列表迭代器首先保证您以列表的内部顺序(又名。插入顺序)获取列表的元素。更具体地说,它是按照您插入元素的顺序或您操作列表的方式。排序可以看作是对数据结构的一种操作,对列表进行排序有多种方式。
我会按照我个人认为的有用性来排序:
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 libraries 有一个TreeMultiset,它的工作原理很像TreeSet。
2。使用Collections.sort() 对您的列表进行排序
如上所述,Lists 的排序是对数据结构的操作。因此,对于您需要以多种方式排序的“一个事实来源”的情况,那么手动排序是可行的方法。
您可以使用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"
使用比较器
一个明显的好处是您可以在sort 方法中使用Comparator。 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 类。
Cmets 中的 Nico Haase 链接到 related question,该 related question 也回答了这个问题。
在排序的集合中你很可能不想操作内部数据结构,这就是 PriorityQueue 不实现 List 接口的原因(因为这会让你直接访问它的元素) .
注意PriorityQueue 迭代器
PriorityQueue 类实现了Iterable<E> 和Collection<E> 接口,因此可以像往常一样对其进行迭代。但是,迭代器不能保证按排序顺序返回元素。相反(正如 Alderath 在 cmets 中指出的那样)您需要 poll() 队列直到为空。
请注意,您可以通过constructor that takes any collection 将列表转换为优先级队列:
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();
}
}
请注意,如果您没有覆盖您需要的方法,那么来自AbstractList 的默认实现将抛出UnsupportedOperationExceptions。