使用Java的Stream流实现词频统计功能

1.使用分组和计数函数来实现词频统计
	@Test
    public void test() throws IOException {
        //定义要加载的文件位置
        String path = "word.txt";

        //通过Files.lines获取字符流对象
        Stream<String> stream = Files.lines(Path.of(path));

        stream = stream.flatMap(x-> Arrays.stream(x.split(" ")));

        Map<String, Long> collect = stream.collect(Collectors.groupingBy(x -> x, Collectors.counting()));
        
        System.out.println(collect);
    }

其中的自定义文件内容为:
在这里插入图片描述
单词之间以空格进行分割。

Stream<String> stream = Files.lines(Path.of(path));

Files.lines() 接收一个 Path 对象,然后读取文件中的每一行转化为流之后赋值给 Stream 对象。
此时的 stream 内容为:[[“Java is very good”],[“python is very young”],[“C++ is very fast”]]。

stream = stream.flatMap(x-> Arrays.stream(x.split(" ")));

使用 stream.flatMap 使流数据扁平化,即在每个x中对字符串以空格进行分割然后返回流对象。运行完后 stream 的内容为:在这里插入图片描述

stream.collect(Collectors.groupingBy(x -> x, Collectors.counting()));

使用 groupingBy 对单词进行分组,此时分组的就是单词的本身,分组的过程中使用下游收集器对分组后的单词进行统计个数后返回一个Map集合,key为单词,value为重复出现次数。执行完输出结果为:在这里插入图片描述

2.使用分组和下游收集器来实现词频统计
	@Test
    public void test() throws IOException {
        //定义要加载的文件位置
        String path = "word.txt";

        //通过Files.lines获取字符流对象
        Stream<String> stream = Files.lines(Path.of(path));

        stream = stream.flatMap(x-> Arrays.stream(x.split(" ")));

        Map<String, Integer> collect = stream.collect(Collectors.groupingBy(x -> x, Collectors.collectingAndThen(Collectors.toList(), List::size)));
        
        System.out.println(collect);
    }
stream.collect(Collectors.groupingBy(x -> x, Collectors.collectingAndThen(Collectors.toList(), List::size)));

collectionAndThen 收集器在收集器后面添加一个最终处理步骤。把所有相同的单词放入一个List集合后,统计集合的大小,此时集合的大小就是相同单词的数量。然后返回以分组的值为key,最终计算结果为value的Map对象。
运行结果同上。

3.使用分组和自定义计数来实现词频统计
	@Test
    public void test() throws IOException {
        //定义要加载的文件位置
        String path = "word.txt";

        //通过Files.lines获取字符流对象
        Stream<String> stream = Files.lines(Path.of(path));

        stream = stream.flatMap(x-> Arrays.stream(x.split(" ")));

        Map<String, List<String>> collect = stream.collect(Collectors.groupingBy(x -> x));
        collect.values().stream().map(x->{
            Map<String,Integer> map = new HashMap<>();
            map.put(x.get(0),x.size());
            return map;
        }).forEach(System.out::println);
    }
Map<String, List<String>> collect = stream.collect(Collectors.groupingBy(x -> x));

首先根据单词进行分组,分组后的Map集合为:在这里插入图片描述

collect.values().stream().map(x->{
        Map<String,Integer> map = new HashMap<>();
        map.put(x.get(0),x.size());
        return map;
    }).forEach(System.out::println);

此时collect,values()的值为:在这里插入图片描述
对每个值进行 map.put(x.get(0),x.size) 的计算。以第一个元素为例:此时的x=[“very”,“very”],x.get(0) = “very”, x.size() = 2; 返回的为{“very”,2}的map对象,后遍历输出,结果如上。

4.使用toMap方法实现词频统计
    @Test
    public void test() throws IOException {
        //定义要加载的文件位置
        String path = "word.txt";

        //通过Files.lines获取字符流对象
        Stream<String> stream = Files.lines(Path.of(path));

        stream = stream.flatMap(x-> Arrays.stream(x.split(" ")));

        Map<String, Integer> collect = stream.collect(Collectors.toMap(x -> x, x -> 1, (oldValue, newValue) -> oldValue + newValue));
        
        System.out.println(collect);
    }

Map<String, Integer> collect = stream.collect(Collectors.toMap(x -> x, x -> 1, (oldValue, newValue) -> oldValue + newValue));

toMap 方法的三个参数,第一个为作为 key 的对象,第二个为作为 value 的值,第三个是当 Map 中已有 key 是如何处理 oldValue 和 newValue 之间的关系。
以 “very” 为例:当遇见第一个“very”后相当于执行 put(“very”,1) 操作,当再次执行 put(“very”,1) 操作时会出现异常,此时的处理办法是执行 put(“very”, get(“very”)+1) 操作。即lambda表达式的 (oldValue, newValue) -> oldValue+newValue

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值