Java流过滤器值的总和

时间:2017-05-21 20:10:02

标签: java java-8 java-stream

我有一个名为MonitoredData的类,用于描述活动,开始时间和结束时间。属性为activityLabelstartTimeendTime。我必须使用流分组和过滤这些活动,这些活动的总持续时间超过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>

4 个答案:

答案 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());