使用Java Stream API统计含目标元素的子列表去重计数
需求说明
现有两个列表:
list1:存储若干待匹配的目标城市名称list2:嵌套列表,每个子列表对应一名用户的到访城市集合,一个子列表代表一名用户去过的所有城市。例如示例中Person1去过Rome、Amsterdam和Vienna,Person2去过Amsterdam、Barcelona和Milan
需要实现的统计逻辑:
统计去过list1中任意城市的用户总数量,不可重复计数:如果某名用户去过list1中的多个城市,仅计数1次。要求基于Java Stream API实现逻辑。
示例输入与预期结果
list1 = ["Barcelona", "Milan", "Athens"]; list2 = [["Rome", "Amsterdam", "Vienna"], ["Amsterdam", "Barcelona", "Milan"], ["Paris", "Athens"], ["Istanbul", "Barcelona", "Milan", "Athens"]]; // 预期返回结果:3 // 两个列表均为前置Stream操作通过Collectors.toList()生成的结果
实现方案
核心思路是先将目标城市列表转为哈希集合降低匹配时间复杂度,再按用户维度判断是否存在到访城市与目标集合的交集,最终统计符合条件的用户数,代码实现如下:
import java.util.HashSet; import java.util.List; import java.util.Set; // 先将目标城市转为HashSet,把单次contains判断的时间复杂度从O(n)降到O(1),提升匹配效率 Set<String> targetCitySet = new HashSet<>(list1); long matchedUserCount = list2.stream() // 按用户维度过滤:只要用户到访城市中有任意一个属于目标集合,就判定为符合条件 .filter(userVisitedCities -> userVisitedCities.stream().anyMatch(targetCitySet::contains)) .count();
逻辑说明
- 预转
HashSet是性能优化项:如果直接用list1做contains判断,每次匹配都要线性扫描列表,数据量较大时性能损耗明显 filter操作以单个用户的到访列表为处理单位,只要匹配到一个目标城市就会保留该用户,天然满足「单用户匹配多城市仅计数1次」的要求,不会出现重复统计问题- 上述代码跑示例输入时,会过滤掉第一个无匹配城市的用户,最终统计结果为3,和预期完全一致
内容的提问来源于stack exchange,提问作者Bern Kass
相关产品推荐
相关产品推荐

