V. *_*tis 9 java java-8 java-stream
我有一个叫做的类MonitoredData,它描述了一个活动,它的开始时间和结束时间.属性是activityLabel,startTime,endTime.我必须使用流分组和过滤这些活动,这些活动的总持续时间超过10小时.我设法计算持续时间的总和,并根据活动将它们分组:
Map<String, Long> map4 = new HashMap<String, Long>();
map4 = data.stream()
.collect(
Collectors.groupingBy(
MonitoredData::getActivity,
Collectors.summingLong(MonitoredData::getDuration)
)
); //getDuration returns end Time - startTime in milliseconds
Run Code Online (Sandbox Code Playgroud)
但我还没有设法添加过滤器.我试过用:
.filter(Collectors.summingLong(MonitoredData::getDuration) > whatever)
Run Code Online (Sandbox Code Playgroud)
但显然它不起作用.我怎样解决这个问题才能让它返回Map<String, Long>?
我会先做你已经做过的事情:我会将MonitoredData实例流收集到地图中,按活动分组并总结每个值中每个活动的持续时间:
Map<String, Long> map4 = data.stream()
.collect(Collectors.groupingBy(
MonitoredData::getActivity,
HashMap::new,
Collectors.summingLong(MonitoredData::getDuration)));
Run Code Online (Sandbox Code Playgroud)
细微差别在于我正在使用接受工厂的重载版本Collectors.groupingBy,因为在下一步中我想删除持续时间少于10小时的条目,并且规范不保证地图返回通过Collectors.groupingBy采用一个或两个参数的方法是可变的.
这是我删除不匹配的条目的方法:
public static final long TEN_HOURS_MS = 10 * 60 * 60 * 1000;
map4.values().removeIf(v -> v < TEN_HOURS_MS);
Run Code Online (Sandbox Code Playgroud)
如果您想在一行中执行所有操作,则可能需要使用Collectors.collectingAndThen:
Map<String, Long> map4 = data.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(
MonitoredData::getActivity,
HashMap::new,
Collectors.summingLong(MonitoredData::getDuration)),
m -> { m.values().removeIf(v -> v < TEN_HOURS_MS); return m; } ));
Run Code Online (Sandbox Code Playgroud)
在这里,我习惯Collectors.collectingAndThen修改返回的地图Collectors.groupingBy.并且,在finisher函数中,我使用了它Collection.removeIf,它接受一个谓词并删除与该谓词匹配的所有条目.
我认为这就是你想要的,使用 Google Guava Maps 类:
Map<String, Long> map = Maps.filterValues(data.stream()
.collect(Collectors.groupingBy
(MonitoredData::getActivity, Collectors.summingLong
(MonitoredData::getDuration)
)), value -> value > 3);
Run Code Online (Sandbox Code Playgroud)
显然,您可以编写自己的方法来过滤映射,但由于它已经存在,在如此流行的库上...如何使用纯流来做到这一点:我不知道,但也许这会令人满意。