《Effective Java》 第45条书中范例有误

本文探讨了如何使用Java Stream API从字典文件中读取单词,找到并打印所有变位词(同位词)组,对比了传统方法与使用Stream的方法,并针对Stream方法中因按行读取导致的问题进行了修正,引入了flatMap和distinct操作来正确处理单词。
摘要由CSDN通过智能技术生成

阅读 第45条 明智审慎地使用 Stream 时,用书中的范例代码测试时,没使用Stream的范例和使用Stream后的范例测试结果不一样。

该程序从字典文件中读取单词并打印其大小符合用户指定的最小值的所有变位词(anagram)组。如果两个单词由长度相通,不同顺序的相同字母组成,则它们是变位词。程序从用户指定的字典文件中读取每个单词并将单词放入 map 对象中。map 对象的键是按照字母排序的单词,因此『staple』的键是『aelpst』,『petals』的键也是『aelpst』:这两个单词就是同位词,所有的同位词共享相同的依字母顺序排列的形式(或称之为alphagram)。map 对象的值是包含共享字母顺序形式的所有单词的列表。 处理完字典文件后,每个列表都是一个完整的同位词组。然后程序遍历 map 对象的 values() 的视图并打印每个大小符合阈值的列表:

public class Anagrams {
    public static void main(String[] args) throws IOException {
        File dictionary = new File(args[0]);
        int minGroupSize = Integer.parseInt(args[1]);
        Map<String, Set<String>> groups = new HashMap<>();
        try (Scanner s = new Scanner(dictionary)) {
            while (s.hasNext()) {
                String word = s.next();
                groups.computeIfAbsent(alphabetize(word),
                        (unused) -> new TreeSet<>()).add(word);
            }
        }

        for (Set<String> group : groups.values())
            if (group.size() >= minGroupSize)
                System.out.println(group.size() + ": " + group);
    }

    private static String alphabetize(String s) {
        char[] a = s.toCharArray();
        Arrays.sort(a);
        return new String(a);
    }
}

使用Stream,书中原代码:

// Tasteful use of streams enhances clarity and conciseness
public class Anagrams {
    public static void main(String[] args) throws IOException {
        Path dictionary = Paths.get(args[0]);
        int minGroupSize = Integer.parseInt(args[1]);
        try (Stream<String> words = Files.lines(dictionary)) {
            words.collect(groupingBy(word -> alphabetize(word)))
                    .values().stream()
                    .filter(group -> group.size() >= minGroupSize)
                    .forEach(g -> System.out.println(g.size() + ": " + g));
        }
    }

    // alphabetize method is the same as in original version
}

这里有一个问题,Files.lines()是按行读取的,不是按单词读取的。所以测试的结果与第一个示例不一样。

修改后如下:

public class Anagrams {
    public static void main(String[] args) throws IOException {
        Path dictionary = Paths.get(args[0]);
        int minGroupSize = Integer.parseInt(args[1]);

        try (Stream<String> words = Files.lines(dictionary)) {
            words.map(word -> word.split(" ")) // 将行按空格拆分单词                                    
                    .flatMap(Arrays::stream)   // 将各个生成流扁平化为单个流
                    .distinct()                // 去除重复
                    .collect(groupingBy(word -> alphabetize(word)))
                    .values().stream()
                    .filter(group -> group.size() >= minGroupSize)
                    .forEach(group -> System.out.println(group.size() + ": " + group));
        }
    }

    // alphabetize method is the same as in original version
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值