本文共 4061 字,大约阅读时间需要 13 分钟。
这里描述的多态算法是Java平台提供的可重用功能的一部分。它们都来自集合类,它们都采用静态方法的形式,其第一个参数是要执行操作的集合。Java平台提供的绝大多数算法都是在列表实例上操作的,但是其中一些算法是在任意的集合实例上操作的。本节简要介绍以下算法:
排序算法重新排序一个列表,使其元素按照排序关系按升序排列。提供了两种形式的操作。这个简单的表单会根据元素的自然排序来排序。如果您不熟悉自然排序的概念,请阅读对象订购部分。
排序操作使用一个稍微优化的合并排序算法,它快速且稳定:
Fast:它保证在n log(n)时间运行,并且在几乎已排序的列表上运行得更快。经验测试表明,它与高度优化的快速排序一样快。快速排序通常被认为比合并排序快,但不稳定,不能保证nlog (n)性能。
稳定:它不重新排列相等的元素。如果在不同的属性上重复排序相同的列表,这一点很重要。如果一个邮件程序的用户通过邮件发送日期对收件箱进行排序,然后通过发送方对其进行排序,那么用户自然会期望从给定的发送者(仍然)中已经连续的消息列表按邮件日期进行排序。只有当第二种情况稳定时,才有保证。 下面的小程序用词典(字母)顺序打印出它的参数。import java.util.*;public class Sort { public static void main(String[] args) { Listlist = Arrays.asList(args); Collections.sort(list); System.out.println(list); }}
让我们运行这个程序。
args = {“%”, “java”, “Sort”, “i”, “walk”, “the”, “line”};
产生以下输出。[%, Sort, i, java, line, the, walk]
这是个简单的程序,算法真的很容易使用,就像它们看起来一样。排序的第二种形式是在列表中添加比较器,并将元素与比较器进行排序。假设您想要从我们前面的示例中以最大的anagram组的倒序顺序打印出anagram组。下面的示例向您展示了如何在排序方法的第二种形式的帮助下实现这一点。
回想一下,anagram组以列表实例的形式存储为Map中的值。修改后的打印代码遍历映射的values视图,将每个通过最小大小测试的列表放入列表列表中。然后,代码对这个列表进行排序,使用期望列表实例的比较器,并实现反向排序。最后,代码遍历已排序的列表,打印它的元素(anagram组)。下面的代码替换了Anagrams示例中main方法末尾的打印代码。
// Make a List of all anagram groups above size threshold.List
> winners = new ArrayList
>();for (List l : m.values()) if (l.size() >= minGroupSize) winners.add(l);// Sort anagram groups according to sizeCollections.sort(winners, new Comparator
>() { public int compare(List o1, List o2) { return o2.size() - o1.size(); }});// Print anagram groups.for (List l : winners) System.out.println(l.size() + ": " + l);
在与Map接口部分相同的字典中运行程序,与最小的anagram组大小(8)相同,产生以下输出。
12: [apers, apres, asper, pares, parse, pears, prase, presa, rapes, reaps, spare, spear]11: [alerts, alters, artels, estral, laster, ratels, salter, slater, staler, stelar, talers]10: [least, setal, slate, stale, steal, stela, taels, tales, teals, tesla]9: [estrin, inerts, insert, inters, niters, nitres, sinter, triens, trines]9: [capers, crapes, escarp, pacers, parsec, recaps, scrape, secpar, spacer]9: [palest, palets, pastel, petals, plates, pleats, septal, staple, tepals]9: [anestri, antsier, nastier, ratines, retains, retinas, retsina, stainer, stearin]8: [lapse, leaps, pales, peals, pleas, salep, sepal, spale]8: [aspers, parses, passer, prases, repass, spares, sparse, spears]8: [enters, nester, renest, rentes, resent, tenser, ternes,��treens]8: [arles, earls, lares, laser, lears, rales, reals, seral]8: [earings, erasing, gainers, reagins, regains, reginas, searing, seringa]8: [peris, piers, pries, prise, ripes, speir, spier, spire]8: [ates, east, eats, etas, sate, seat, seta, teas]8: [carets, cartes, caster, caters, crates, reacts, recast,��traces]
shuffle算法的作用与排序相反,破坏了列表中可能出现的任何顺序。也就是说,这个算法根据来自随机源的输入重新排序列表,这样所有可能的排列都有相同的可能性,假设有一个合理的随机性来源。该算法对实现概率游戏有一定的参考价值。例如,它可以用来洗牌一列表示牌组的牌对象。此外,它还有助于生成测试用例。
该操作有两种形式:一种使用列表,使用默认的随机性源,另一种要求调用者提供随机对象作为随机性的来源。该算法的代码被用作列表部分中的一个示例。
集合类提供了用于在列表对象上执行常规数据操作的五种算法,它们都非常简单:
binarySearch算法在排序列表中搜索指定的元素。该算法有两种形式。第一个获取一个列表和一个元素来搜索(“搜索键”)。此表单假定列表按照其元素的自然顺序按升序排序。第二种表单除了列表和搜索键之外,还有一个比较器,并假定列表按照指定的比较器按升序排序。排序算法可以在调用binarySearch之前对列表进行排序。
两种形式的返回值相同。如果列表包含搜索键,则返回其索引。如果没有,返回值是(-(插入点)- 1),插入点的位置的值将被插入到列表,或大于第一个元素的索引值或list.size()如果列表中的所有元素都小于指定值。这个公认的丑陋的公式保证返回值将是>= 0,如果且仅当搜索键被找到时。它基本上是将一个布尔(找到的)和一个整数(索引)合并成一个int返回值的方法。
下面的习惯用法可以使用两种形式的binarySearch操作,查找指定的搜索键,并在不存在的情况下将其插入适当的位置。
int pos = Collections.binarySearch(list, key);if (pos < 0) l.add(-pos-1, key);
frequency和disjoint算法测试一个或多个集合的组成部分:
frequency——计数指定元素在指定集合中发生的次数。
disjoint-确定两个集合是否分离;也就是说,它们是否包含相同的元素。min和max算法分别返回指定集合中包含的最小和最大元素。这两种操作都有两种形式。这个简单的表单只接受一个集合,并根据元素的自然排序返回最小(或最大)元素。第二种形式在集合中添加一个比较器,并根据指定的比较器返回最小(或最大)元素。
转载地址:http://ueqab.baihongyu.com/