Java8 流和过滤器

Java8 streams and filters

我有一个 set 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 的流和过滤器实现相同的行为?

您可以使用 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));

请注意,您正在做不必要的工作。看看 SetMultimap.get:

Returns a view collection of the values associated with key in this multimap, if any. Note that when containsKey(key) is false, this returns an empty collection, not 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());

并且不会随着流变得更好......