繁体   English   中英

Collectors.summingInt() 和 Collectors.joining()

[英]Collectors.summingInt() and Collectors.joining()

我有一个Cat class,它有String nameint tailLength字段以及String getName()int getTailLength()方法。 Cat实例被放置在List<Cat> cats中。 我的问题:

为什么这可以正常工作:

int tailsEndToEnd = cats.stream().collect(Collectors.summingInt(Cat::getTailLength); //(1)

这不会:

String allNames = cats.stream().collect(Collectors.joining(Cat::getName); //(2)

我知道我可以像这样收集猫的名字:

cats.stream().collect(Collectors.mapping(Cat::getName, joining(", ")); //(3),

只是好奇为什么(2)不起作用,看到它完全类似于(1),不管 output 看起来如何(没有逗号等)。

谢谢

所有Collector.joining变体都返回一个Collector<CharSequence, ?, String> ,这意味着它们只能对Stream<CharSequence>进行操作。

当您使用Collectors.mapping(Cat::getName,joining(", ")); mapping将您的Stream<Cat>转换为Stream<CharSequence>, which allows that Stream to be processed by join()` 处理。

您不能使用 Join 直接处理Stream<Cat> ,因为它没有接受映射joining以将您的Cat转换为String的变体。 joining的所有 arguments 都是CharSequence ,用作分隔符、前缀或后缀。

这与summingInt不同,后者接受ToIntFunction<? super T> ToIntFunction<? super T>映射器 function 到 map 将Stream的元素转换为int

Eran 的回答基本上总结了它,我只是想在您的具体情况下补充一点,实现您想要的更惯用(并且绝对更具可读性)的方式是:

String catNames = cats.stream().map(Cat::getName).collect(Collectors.joining());

这样每个操作都可以独立检查,因此易于阅读和理解:

  1. Map 猫名单到他们名字的名单
  2. 将猫名列表加入单个字符串

而在您的第三个示例中,您正在执行collect内部的两个操作,这不太自然。

我没有看到解决的问题是接受一个参数的 Collectors.joining 方法只接受一个 CharSequence 作为参数:

公共 static ... 加入(字符序列分隔符)

(这里重要的不是返回类型,而是方法参数定义。)

Cat::getName不是 CharSequence,它是一个方法引用(可以解释为一个函数)。 它永远不会是该方法的合适论据。

正如其他人所说,您需要先将 map 转换为字符串,然后调用 Collections.joining,使用零 arguments 或使用单个分隔符参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM