Java 进阶 -- 集合(四)

5、算法

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

  • 排序(Sorting)
  • 打乱顺序(Shuffling)
  • 常规数据操作
  • 搜索(Searching)
  • 组成操作
  • 寻找极值

5.1 排序

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实例的ComparatorList进行排序,并实现反向大小排序。最后,代码遍历排序后的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);

5.2 Shuffling

shuffle算法所做的与sort相反,它会破坏List中可能存在的任何顺序跟踪。也就是说,该算法根据来自随机源的输入对List进行重新排序,以便在假设随机源公平的情况下,所有可能的排列都以相同的可能性发生。这个算法在执行机会游戏时很有用。例如,它可以用来洗牌代表牌组的卡牌(Card)对象列表。此外,它对于生成测试用例也很有用。

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

5.3 常规数据操作

Collections类提供了五种算法来对List对象进行日常数据操作,所有这些算法都非常简单:

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

5.4 搜索

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

5.5 组成

频率和不相交算法测试一个或多个Collections组成的某些方面:

  • frequency – 对指定元素在指定集合中出现的次数进行计数
  • disjoint – 确定两个集合是否不相交; 也就是说,它们是否不包含共同的元素

5.6 寻找极值

minmax算法分别返回指定Collection中包含的最小和最大元素。这两种操作都有两种形式简单表单只接受一个Collection,并根据元素的自然顺序返回最小(或最大)元素。第二种形式除了接受Collection之外还接受一个Comparator,并根据指定的Comparator返回最小(或最大)元素。

Supongo que te gusta

Origin blog.csdn.net/chinusyan/article/details/131089987
Recomendado
Clasificación