我想计算一个流的不同元素,想知道为什么

Stream<String> stream = Stream.of("a", "b", "a", "c", "c", "a", "a", "d");
Map<String, Integer> counter1 = stream.collect(Collectors.toMap(s -> s, 1, Integer::sum));

不起作用。 Eclipse告诉我



顺便说一下,我知道该解决方案:
Map<String, Long> counter2 = stream.collect(Collectors.groupingBy(s -> s, Collectors.counting()));

所以我有两个问题:
  • 第一种方法有什么错误?
  • 您将如何实现这样的计数器?

  • 编辑:我自己解决了第一个问题:
    Map<String, Integer> counter1 = stream.collect(Collectors.toMap(s -> s, s -> 1, Integer::sum));
    

    Java期望将函数作为第二个参数。

    最佳答案

    确实有几种方法可以做到这一点。你没有提到的是.collect(groupingBy(x -> x, summingInt(x -> 1)));
    在性能上有一些差异。

    如果每个存储桶中的对象很少,则方法1将达到最佳状态。在每个存储桶只有1个对象的理想情况下,无需修改条目即可立即获得最终 map 。在具有大量重复对象的最坏情况下,它将必须进行大量装箱/拆箱。

    方法2依赖于counting()收集器,它没有确切指定应该如何进行计数。当前的实现转发到reducing,但是可能会改变。
    summingInt方法将在int中而不是在Integer中累积计数,因此不需要装箱/拆箱。如果对象重复很多次,那将是最佳状态。

    至于选择哪一个,最好是为了清楚起见进行编码,并在必要时进行优化。对我来说,groupingBy(x->x, counting())最清楚地表达了这个意图,所以我很愿意这样做。

    08-05 07:25