Java 集合框架 算法

这里描述的多态算法是Java平台提供的可重用功能的一部分。它们都来自集合类,它们都采用静态方法的形式,其第一个参数是要执行操作的集合。Java平台提供的绝大多数算法都是在列表实例上操作的,但是其中一些算法是在任意的集合实例上操作的。本节简要介绍以下算法:

  • 排序
  • 洗牌(打乱顺序)
  • 常规数据操作
  • 搜索
  • 构成
  • 找到极值

排序

排序算法重新排序一个列表,使其元素按照排序关系按升序排列。提供了两种形式的操作。这个简单的表单会根据元素的自然排序来排序。如果您不熟悉自然排序的概念,请阅读对象订购部分。

排序操作使用一个稍微优化的合并排序算法,它快速且稳定:

Fast:它保证在n log(n)时间运行,并且在几乎已排序的列表上运行得更快。经验测试表明,它与高度优化的快速排序一样快。快速排序通常被认为比合并排序快,但不稳定,不能保证nlog (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);
    }
}

让我们运行这个程序。

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<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);

在与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算法的作用与排序相反,破坏了列表中可能出现的任何顺序。也就是说,这个算法根据来自随机源的输入重新排序列表,这样所有可能的排列都有相同的可能性,假设有一个合理的随机性来源。该算法对实现概率游戏有一定的参考价值。例如,它可以用来洗牌一列表示牌组的牌对象。此外,它还有助于生成测试用例。

该操作有两种形式:一种使用列表,使用默认的随机性源,另一种要求调用者提供随机对象作为随机性的来源。该算法的代码被用作列表部分中的一个示例。

常规数据操作

集合类提供了用于在列表对象上执行常规数据操作的五种算法,它们都非常简单:

  • reverse-反转列表中元素的顺序。
  • fill-覆盖列表中的每个元素,并具有指定的值。这个操作对于重新初始化一个列表非常有用。
  • copy-接受两个参数,一个目标列表和一个源列表,并将源的元素复制到目标中,覆盖其内容。目标列表必须至少和源代码一样长。如果它较长,则目标列表中的其余元素不会受到影响。
  • swap——在列表中的指定位置交换元素。
  • addAll—将所有指定元素添加到集合中。要添加的元素可以单独指定,也可以作为数组来指定。

搜索

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算法分别返回指定集合中包含的最小和最大元素。这两种操作都有两种形式。这个简单的表单只接受一个集合,并根据元素的自然排序返回最小(或最大)元素。第二种形式在集合中添加一个比较器,并根据指定的比较器返回最小(或最大)元素。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值