如何将 Collectors.collectingAndThen 与 Collectors.groupingBy 一起使用

bbK*_*ing 2 java java-stream

以以下列表为例:

List<String> input = List.of("FOO", "FOO", "FOO", "FOO", "FOO", "BAR", "BAR", "BAZ", "BAZ", "BAZ", "DOO", "DOO"); 
Run Code Online (Sandbox Code Playgroud)

我需要获取每个元素的相对频率并将其格式化为字符串。为此,我使用了两个步骤,首先创建频率图,然后计算相对百分比和格式:

Map<String, Long> relativeFrequency =
        input.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));

Map<String, String> relativeFrequency2 = relativeFrequency.entrySet().stream()
        .collect(Collectors.toMap(Map.Entry::getKey,
                entry -> String.format ( "%.02f%%", entry.getValue() * 100.  / input.size() )));

System.out.println(relativeFrequency2);
Run Code Online (Sandbox Code Playgroud)

并得到结果

{BAR=16.67%, DOO=16.67%, FOO=41.67%, BAZ=25.00%}
Run Code Online (Sandbox Code Playgroud)

我被告知要重构上述内容并使用Collectors.collectingAndThen一次性完成,但我似乎找不到正确的语法(编译错误Operator '*' cannot be applied to '<lambda parameter>', 'double')。有人可以帮助纠正以下内容以获得与上面相同的结果吗?

Map<String, String> relativeFrequency3 = 
input.stream().collect(Collectors.collectingAndThen(Collectors.groupingBy(Function.identity(), Collectors.counting(),
                total -> String.format ( "%.02f%%", total * 100.  / input.size() ))
));
Run Code Online (Sandbox Code Playgroud)

WJS*_*WJS 6

你很接近。

List<String> input =
        List.of("FOO", "FOO", "FOO", "FOO", "FOO", "BAR",
                "BAR", "BAZ", "BAZ", "BAZ", "DOO", "DOO");
Run Code Online (Sandbox Code Playgroud)
  • 第一个参数collectingAndThencounting()获取频率。
  • 然后您可以通过将其转换为格式化百分比来处理该频率。
Map<String, String> map = input.stream().collect(Collectors
        .groupingBy(a -> a, Collectors.collectingAndThen(
                Collectors.counting(),
                count -> "%.2f%%".formatted((double) count
                        / input.size() * 100))));
        
map.entrySet().forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

打印每个条目集产量

BAR=16.67%
DOO=16.67%
FOO=41.67%
BAZ=25.00%
Run Code Online (Sandbox Code Playgroud)

  • 这是 JDK 13 中的一个预览功能,在同一版本中被标记为已弃用,这是标记预览功能的糟糕尝试。请参阅[此处](https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/String.html#formatted(java.lang.Object...) )。然后,JDK 14 引入了真正的*预览*功能,因此它被标记为这样,请参阅[此处](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java /lang/String.html#formatted(java.lang.Object...))。从 JDK 15 开始,它就是真正的功能,您知道,并且将保持原样(据我们今天所知)。您可以继续使用它。 (2认同)