我有一个名为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
但我还没设法添加过滤器。我尝试使用:
.filter(Collectors.summingLong(MonitoredData::getDuration) > whatever)
但显然它不起作用。如何解决这个问题才能让它返回Map<String, Long>
?
答案 0 :(得分:6)
我会先做你已经做过的事情:我会将ports = {'max-api' => 83, 'max-logger' => 82, 'max-data' => 84}
services = %w(max-api max-data max-logger)
services.each do |service|
puts "shell: echo #{service}:#{ports[service]}#{'00' if service != 'max-logger'}"
end
# => shell: echo max-api:8300
# => shell: echo max-data:8400
# => shell: echo max-logger:82
个实例流收集到地图中,按活动分组,并将每个活动的持续时间汇总在每个值中:
MonitoredData
细微差别在于我正在使用overloaded version of Collectors.groupingBy
that accepts a factory for the map,因为在下一步中我想删除持续时间少于10小时的条目,并且规范并不保证地图返回的地图采用一个或两个参数的Map<String, Long> map4 = data.stream()
.collect(Collectors.groupingBy(
MonitoredData::getActivity,
HashMap::new,
Collectors.summingLong(MonitoredData::getDuration)));
方法是可变的。
这就是我删除不匹配条目的方法:
Collectors.groupingBy
如果您想在一行中执行所有操作,可能需要使用public static final long TEN_HOURS_MS = 10 * 60 * 60 * 1000;
map4.values().removeIf(v -> v < TEN_HOURS_MS);
:
Collectors.collectingAndThen
我在这里使用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; } ));
返回的地图。并且,在终结器函数中,我使用了Collection.removeIf
,它接受一个谓词并删除与该谓词匹配的所有条目。
答案 1 :(得分:4)
这个怎么样?我在电话里回答,你需要自己测试。
map = map.entrySet()
.stream()
.filter(it->TimeUnit.MILLISECONDS.toHours(it.getValue())>10)
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
或使用Collectors#collectingAndThen
:
map4 = data.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(
MonitoredData::getActivity,
Collectors.summingLong(MonitoredData::getDuration)
),
r1 -> r1.entrySet().stream()
.filter(it->TimeUnit.MILLISECONDS.toHours(it.getValue())>10)
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue))
));
答案 2 :(得分:3)
我认为这是你想要的,使用 Google Guava Maps class:
Map<String, Long> map = Maps.filterValues(data.stream()
.collect(Collectors.groupingBy
(MonitoredData::getActivity, Collectors.summingLong
(MonitoredData::getDuration)
)), value -> value > 3);
显然你可以编写自己的方法来过滤这样的地图,但由于它已经存在,所以在如此受欢迎的图书馆......如何用纯流来做:我不知道,但是也许这会令人满意。
答案 3 :(得分:2)
获得地图后添加以下代码:
map4.entrySet().stream()
.filter(a -> a.getValue() > whatever)
.collect(Collectors.joining());