如何用Java Stream实现按School描述统计数量的Map<String, Long>?
问题分析与解决建议
你的代码问题出在混淆了toMap和groupingBy收集器的用法,这两个不能像你那样嵌套使用——toMap的第二个参数需要的是元素到值的映射函数(或重复键的合并函数),而不是另一个收集器,类型不匹配导致代码无法运行。
正确的写法(推荐)
直接使用Collectors.groupingBy搭配Collectors.counting(),这是实现分组计数最直观、简洁的方式:
Stream<School> schoolStream = getSchools().stream(); Map<String, Long> descriptionCountMap = schoolStream.collect( Collectors.groupingBy(School::getDescription, Collectors.counting()) );
groupingBy(School::getDescription):指定以学校的描述字符串作为Map的键,完成分组逻辑counting():自动统计每个分组内的School实例数量,作为Map对应键的值
为什么原代码不行?
Collectors.toMap的核心签名是:
toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper)
你传入的第二个参数groupingBy(...)是一个Collector类型,和方法要求的Function类型完全不匹配,所以编译会直接报错。
另一种实现方式(用toMap)
如果你非要用toMap来实现需求,可以通过给每个元素映射初始计数1,再合并重复键的计数来达成:
Map<String, Long> descriptionCountMap = schoolStream.collect( Collectors.toMap( School::getDescription, s -> 1L, // 每个学校对应初始计数1 Long::sum // 遇到重复描述时,累加计数 ) );
不过这种写法在分组计数场景下不如groupingBy直观,优先推荐第一种方案。
内容的提问来源于stack exchange,提问作者simondvt
相关产品推荐
相关产品推荐

