使用reduce方法计算文件Java8中的单词

时间:2018-03-01 05:59:08

标签: java java-stream reduce

我想用java8中的reduce来计算文件中出现的单词任何帮助表示我不想使用收集器或地图到目前为止我的代码是;

filecontent.flatMap(line->Stream.of(line.split("\\s+")))
                       .map(String::toLowerCase)
                       .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));   
  //here I want to replace colect() with reduce

2 个答案:

答案 0 :(得分:1)

首先,您应在问题中提供完整的可编辑示例,例如:

Stream<String> filecontent = Stream.of("foo in bar is foo", "bar in bar is not foo");
Map<String, Long> result = filecontent.flatMap(line -> Stream.of(line.split("\\s+")))
    .map(String::toLowerCase)
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

然后要减少,你需要使用Map对象来减少(为简洁起见,使用Java HashMap,这不是这种情况下最有效的数据结构):

Stream<String> filecontent = Stream.of("foo in bar is foo", "bar in bar is not foo");
Map<String, Long> result = filecontent.flatMap(line -> Stream.of(line.split("\\s+")))
    .map((word) -> singletonMap(word.toLowerCase(), 1L))
    .reduce(new HashMap<>(), (map1, map2) -> {
        for (Map.Entry<String, Long> entry: map2.entrySet()) {
            map1.put(entry.getKey(), map1.getOrDefault(entry.getKey(), 0L) + entry.getValue());
        }
        return map1;
    });

这将首先创建一个新的空HashMap,然后为每个新单词创建一个单独的Hashmap,并在每个reduce步骤中将这样的单个映射合并到原始的hashmap中。如果要使用并行流执行此操作,则需要在reduce步骤中创建新映射:

        Map<String, Long> tempResult = new HashMap<>(map1);
        for (Map.Entry<String, Long> entry: map2.entrySet()) {
            tempResult.put(entry.getKey(), map1.getOrDefault(entry.getKey(), 0L) + entry.getValue());
        }
        return tempResult;

答案 1 :(得分:0)

受@ tkruse的回答启发,我想出了以下片段:

Stream<String> fileContent = Stream.of("foo in bar is foo", "bar in bar is not foo");
Pattern pattern = Pattern.compile("\\s+");
Map<String, Long> result = fileContent
    .flatMap(pattern::splitAsStream)
    .reduce(new HashMap<String, Long>(), (map, word) -> {
        map.merge(word, 1L, Long::sum);
        return map;
    }, (left, right) -> {
        right.forEach((key , count ) -> left.merge(key, count, Long::sum));
        return left;
    });

注意第二行创建一个模式,然后在流中使用该模式来分割行。