对问题和练习的答案:

Questions

  • 问题:您打算编写一个使用几个基本集合interface的程序:SetListQueueMap。您不确定哪种实现效果最佳,因此您决定使用通用实现,直到您更好地了解程序在现实世界中的工作方式。这些是哪些实现?
    Answer:
    SetHashSet
    ListArrayList
    QueueLinkedList
    MapHashMap

  • 问题:如果您需要提供按值排序的迭代的Set实现,则应使用哪个类?
    Answer:
    TreeSet保证排序后的集合按元素的升序排列,根据元素的自然 Sequences 或提供的Comparator进行排序。

  • 问题:您使用哪个类访问包装器实现?
    Answer:
    您使用Collections类,该类提供对集合进行操作或返回集合的静态方法。

Exercises

  • 练习:编写一个程序,该程序将第一个命令行参数指定的文本文件读入List。然后,程序应从文件中打印随机行,第二行命令行参数指定要打印的行数。编写程序,以便一次分配正确大小的集合,而不是在读取文件时逐渐扩展它。提示:要确定文件中的行数,请使用java.io.File.length获取文件的大小,然后除以假设的平均线尺寸。
    Answer:
    由于我们是随机访问List,因此我们将使用ArrayList。我们通过将文件大小除以 50 来估计行数。然后将这个数字加倍,因为高估比低估更有效。
import java.util.*;
import java.io.*;

public class FileList {
    public static void main(String[] args) {
        final int assumedLineLength = 50;
        File file = new File(args[0]);
        List<String> fileList = 
            new ArrayList<String>((int)(file.length() / assumedLineLength) * 2);
        BufferedReader reader = null;
        int lineCount = 0;
        try {
            reader = new BufferedReader(new FileReader(file));
            for (String line = reader.readLine(); line != null;
                    line = reader.readLine()) {
                fileList.add(line);
                lineCount++;
            }
        } catch (IOException e) {
            System.err.format("Could not read %s: %s%n", file, e);
            System.exit(1);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {}
            }
        }
        int repeats = Integer.parseInt(args[1]);
        Random random = new Random();
        for (int i = 0; i < repeats; i++) {
            System.out.format("%d: %s%n", i,
                    fileList.get(random.nextInt(lineCount - 1)));
        }
    }
}

该程序实际上将大部分时间都花在读取文件上,因此预分配ArrayList对其性能几乎没有影响。当程序在不干预 I/O 的情况下重复创建大型ArrayList对象时,预先指定初始容量可能会很有用。