Java8流与过滤器

3
我有一个存储一些字符串对应月份(整数)的 multimap 集合。
MonthlyCount = {1:["hello"],2:["hello","hi"]}   

我有一张地图,记录了每个月字符串的数量,并进行累加。我使用containsKey过滤器来检查键是否存在于集合中,并将它们添加到地图中。

final String[] months = new DateFormatSymbols().getShortMonths();
final Map<String, Object> metaData = new LinkedHashMap<>();
private SetMultimap<Integer, String> MonthlyCount;

for (int i = 0; i <= month; i++) {
    final int count = MonthlyCount.containsKey(i + 1) ? MonthlyCount.get(i + 1).size() : 0;
    metaData.put(months[i], count);
}

有没有一种使用Java8的流和过滤器实现相同行为的方法?

1
你在操作过程中显然访问另一个Map有何原因?ticketsByMonthMap是什么,为什么在从它获取值之前要检查MonthlyCount中是否存在该键? - Holger
@Holger。感谢您指出这一点。已经更改了。 - Tania
2个回答

5
你可以使用 IntStream 迭代所需的范围,并使用 Collectors.toMap 生成所需的映射:
Map<String,Integer> map =
IntStream.range(0,months.length)
         .boxed()
         .collect(Collectors.toMap(i->months[i], 
                                   i->MonthlyCount.containsKey(i + 1) ? MonthlyCount.get(i + 1).size() : 0));

1
@Tania 我以为它可以不用装箱,但你可以通过对 Stream 进行装箱来轻松解决它。请参见编辑。 - Eran
1
@Tania 我尝试了类似的代码并且它有效。如果您喜欢,您可以将Map的类型更改为 Map<String,Object> - Eran
1
如果两个不同的映射名称不是有意为之,使用 Map.getOrDefault 可以比将循环转换为流来改进代码,即 MonthlyCount.getOrDefault(i+1, emptySet()).size()... - Holger
1
@Tania 你的意思是将它分配给现有的Map变量吗?是的。 - Eran
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Eran
显示剩余8条评论

4
请注意,您在做不必要的工作。请查看SetMultimap.get
返回此多重映射中与key相关联的值的视图集合(如果有)。请注意,当containsKey(key)为false时,这会返回一个空集合而不是null。
因此,在您的循环中,您需要做的只是:
metaData.put(months[i], MonthlyCount.get(i + 1).size());

因为对于不存在的键来说,它的值肯定是零。如果你有一个非Guava的 Map<…,Set<…>>,你可以在Java 8中执行等效操作:

metaData.put(months[i], MonthlyCount.getOrDefault(i + 1, emptySet()).size());

其中emptySet()Collections.emptySet()的静态导入。

当您想要添加到现有的Map时,我不会重写循环以使用流。毕竟,代码已经足够简洁。

for(int i=0; i<month.length; i++)
    metaData.put(months[i], MonthlyCount.get(i + 1).size());

而且不会因为流而变得更好...


在这种情况下,流相对于集合是否能提高性能? - Tania
2
@Tania 不,流式代码在性能上并不比非流式代码更好。 - Louis Wasserman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接