在Java中使用Lambda表达式统计词频

在Java中使用Lambda表达式统计词频

常规方法

使用Java进行词频统计的常规方法步骤如下:

1. 初始化一个map对象实例(用于保存单词以及它的出现次数)和一个变量fre(用于词频临时存放)
2. 遍历每一个需要统计的单词,进行如下操作
    a. 将fre赋值为1
    b. 判断当前单词在map中是否存在
        如果存在,则将fre加上该词在map中存入词频
    c. 将当前单词与fre存入map

以上步骤的代码实现如下:

Map<String, Integer> map = new HashMap<>();
int fre;
for(String word : words) {
    fre = 1;
    if(map.containsKey(word))
        fre += map.get(word);
    map.put(word, fre);
}

使用Lambda表达式

在学习阅读State of the Lambda: Libraries Edition时,发现文中Collectors部分给出的最后一个代码实例存在一个小问题,即counting()方法返回的是长整型的数据类型Long,而Map却是使用Integer接收,显然是存在问题的。

文中的代码实例:

Pattern pattern = Pattern.compile(\\s+");
Map<String, Integer> wordFreq = 
    tracks.stream()
          .flatMap(t -> pattern.splitAsStream(t.name)) // Stream<String>
          .collect(groupingBy(s -> s.toUpperCase(),
                              counting()));

counting()方法的定义如下:

public static <T> Collector<T, ?, Long>
counting() {
    return reducing(0L, e -> 1L, Long::sum);
}

故而,需要使用自定义的counting()方法,如上,仅需要做如下修改即可:

Pattern pattern = Pattern.compile(\\s+");
Map<String, Integer> wordFreq =
        tracks.stream()
            .flatMap(t -> pattern.splitAsStream(t.name)) // Stream<String>
            .collect(groupingBy(s -> s.toUpperCase(),
                                Collectors.reducing(0, e -> 1, Integer::sum)));

假设所有需要统计的单词存于List数组中,那么使用该方法进行词频统计代码如下:

// List<String> list = new ArrayList<>();
// list.add("aa a b A h z B");
// list.add("a a b A h z B");
// list.add("a a b A h z B");
// list.add("a a b A h z B");

Pattern pattern = Pattern.compile("\\s+");
Map<String, Integer> wordFreq =
    list.stream()
            .flatMap(t -> pattern.splitAsStream(t))
            .collect(groupingBy(s -> s, Collectors.reducing(0, e -> 1, Integer::sum)));

在集合(List)上调用stream()生成该集合元素的流视图,然后采用将一个返回流的函数传入flatMap(),这样会产生每个单词,最后将这些词进行统计存入Map中。

猜你喜欢

转载自blog.csdn.net/Subson/article/details/72819131
今日推荐