[英]Java reduce a collection of string to a map of occurence
将列表视为id1_f, id2_d, id3_f, id1_g
,如何使用流来获取统计信息的<String, Integer>
格式的简化映射,如:
id1 2
id2 1
id3 1
注意:键在_
之前是部分。 reduce
功能可以帮助吗?
这将完成工作:
Map<String, Long> map = Stream.of("id1_f", "id2_d", "id3_f", "id1_g")
.collect(
Collectors.groupingBy(v -> v.split("_")[0],
Collectors.counting())
);
您还可以使用toMap
收集器:
myList.stream()
.collect(Collectors.toMap((String s) -> s.split("_")[0],
(String s) -> 1, Math::addExact);
如果您关心元素的顺序,则将结果转储到LinkedHashMap
。
myList.stream()
.collect(Collectors.toMap((String s) -> s.split("_")[0],
(String s) -> 1, Math::addExact,
LinkedHashMap::new));
使用Map :: merge的非流方法:
Map<String, Integer> result = new LinkedHashMap<>();
myList.forEach(s -> result.merge(s.split("_")[0], 1, Math::addExact));
由于你想要计算元素,我建议使用Guava的Multiset
接口,它专门用于此目的。
从JavaDoc中定义Multiset
:
支持与顺序无关的相等的集合,如
Set
,但可能具有重复的元素。 multiset有时也被称为包 。多重集是彼此相等的元件被称为相同的单个元件的出现 。 多集中元素的出现总数称为该元素的计数 。
以下是两种使用方法:
1)没有Stream API:
ImmutableMultiset<String> multiset2 = ImmutableMultiset.copyOf(Lists.transform(
list, str -> StringUtils.substringBefore(str, "_")
));
2)使用Stream API:
ImmutableMultiset<String> multiset = list.stream()
.map(str -> StringUtils.substringBefore(str, "_"))
.collect(ImmutableMultiset.toImmutableMultiset());
请注意,我没有使用类似s.split("_")[0]
,而是使用了Apache Commons Lang的StringUtils.substringBefore
,我发现它更具可读性。
您可以使用Multiset.count()
方法检索元素的计数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.