这里描述的多态算法(polymorphic algorithms
)是Java平台提供的可重用功能。它们都来自Collections类,并且都采用静态方法的形式,其第一个参数是要对其执行操作的集合。Java平台提供的绝大多数算法都在List实例上操作,但其中一些在任意的Collection实例上操作。本节简要介绍以下算法:
sort
算法对List
进行重新排序,使其元素按照排序关系按升序排列。提供了两种操作形式。简单形式接受一个List
,并根据元素的自然顺序对其进行排序。如果您不熟悉自然排序的概念,请阅读对象排序一节。
sort
操作使用稍微优化的归并排序(merge sort
)算法,快速且稳定:
n log(n)
时间内运行,并且在几乎排序的列表上运行得更快。经验测试表明,它与高度优化的快速排序一样快。快速排序通常被认为比归并排序快,但不稳定,不能保证n log(n)
的性能。下面这个简单的程序按字典顺序(字母顺序)打印出它的参数。
import java.util.*;
public class Sort {
public static void main(String[] args) {
List<String> list = Arrays.asList(args);
Collections.sort(list);
System.out.println(list);
}
}
让我们运行程序。
% java Sort i walk the line
将产生以下输出。
[i, line, the, walk]
包含该程序只是为了向您展示算法真的像它们看起来那样容易使用。
第二种形式的sort除了接受一个List
之外还接受一个Comparator
,并使用Comparator
对元素进行排序。假设您希望按照大小的相反顺序打印前面示例中的变位组——首先是最大的变位组。下面的示例向您展示了如何在sort
方法的第二种形式的帮助下实现这一点。
回想一下,变位组以List
实例的形式作为值存储在Map
中。修改后的打印代码遍历Map
的值视图,将每个通过最小大小测试的List
放入List
of Lists中。然后,代码使用需要List
实例的Comparator
对List
进行排序,并实现反向大小排序。最后,代码遍历排序后的List
,打印其元素(变位组)。下面的代码替换Anagrams示例中主方法末尾的打印代码。
// Make a List of all anagram groups above size threshold.
List<List<String>> winners = new ArrayList<List<String>>();
for (List<String> l : m.values())
if (l.size() >= minGroupSize)
winners.add(l);
// Sort anagram groups according to size
Collections.sort(winners, new Comparator<List<String>>() {
public int compare(List<String> o1, List<String> o2) {
return o2.size() - o1.size();
}});
// Print anagram groups.
for (List<String> l : winners)
System.out.println(l.size() + ": " + l);
shuffle
算法所做的与sort
相反,它会破坏List
中可能存在的任何顺序跟踪。也就是说,该算法根据来自随机源的输入对List
进行重新排序,以便在假设随机源公平的情况下,所有可能的排列都以相同的可能性发生。这个算法在执行机会游戏时很有用。例如,它可以用来洗牌代表牌组的卡牌(Card
)对象列表。此外,它对于生成测试用例也很有用。
此操作有两种形式:一种采用List并使用默认的随机性来源,另一种要求调用者提供Random对象作为随机性来源。该算法的代码在列表部分中用作示例。
Collections类提供了五种算法来对List
对象进行日常数据操作,所有这些算法都非常简单:
List
中元素的顺序。List
中的每个元素。此操作对于重新初始化List
很有用。List
和源List
,并将源的元素复制到目标中,覆盖其内容。目标列表必须至少与源列表一样长。如果它较长,则目标列表中的其余元素不受影响。List
中指定位置的元素。Collection
中。要添加的元素可以单独指定,也可以作为一个数组指定。binarySearch
算法在排序List
中搜索指定的元素。该算法有两种形式。第一个方法接受一个List
和一个要搜索的元素(“搜索键”)。这种形式假定List
按照元素的自然顺序按升序排序。第二种形式除了接受List
和搜索键外,还接受Comparator
,并假设List
按照指定的Comparator
升序排序。排序算法可用于在调用binarySearch
之前对List
进行排序。
两种形式的返回值是相同的。如果List
包含搜索键,则返回其索引。如果不是,返回值为(-(insertion point) - 1)
,其中插入点是值将被插入到List
中的点,或者如果List
中的所有元素都小于指定值,则返回值大于该值或List .size()
的第一个元素的索引。这个丑陋的公式保证当且仅当找到搜索键时返回值将>= 0
。它基本上是将一个布尔值(查找)和一个整数(索引)组合成一个int返回值。
下面的习惯用法可用于两种形式的binarySearch
操作,它查找指定的搜索键,并将其插入到不存在的适当位置。
int pos = Collections.binarySearch(list, key);
if (pos < 0)
l.add(-pos-1, key);
频率和不相交算法测试一个或多个Collections
组成的某些方面:
min
和max
算法分别返回指定Collection
中包含的最小和最大元素。这两种操作都有两种形式。简单表单只接受一个Collection
,并根据元素的自然顺序返回最小(或最大)元素。第二种形式除了接受Collection之外还接受一个Comparator,并根据指定的Comparator返回最小(或最大)元素。