How to map to multiple elements with Java 8 streams?

后端 未结 2 707
滥情空心
滥情空心 2020-12-24 01:20

I have a class like this:

class MultiDataPoint {
  private DateTime timestamp;
  private Map keyToData;
}

and i want

2条回答
  •  心在旅途
    2020-12-24 01:29

    To do this, I had to come up with an intermediate data structure:

    class KeyDataPoint {
        String key;
        DateTime timestamp;
        Number data;
        // obvious constructor and getters
    }
    

    With this in place, the approach is to "flatten" each MultiDataPoint into a list of (timestamp, key, data) triples and stream together all such triples from the list of MultiDataPoint.

    Then, we apply a groupingBy operation on the string key in order to gather the data for each key together. Note that a simple groupingBy would result in a map from each string key to a list of the corresponding KeyDataPoint triples. We don't want the triples; we want DataPoint instances, which are (timestamp, data) pairs. To do this we apply a "downstream" collector of the groupingBy which is a mapping operation that constructs a new DataPoint by getting the right values from the KeyDataPoint triple. The downstream collector of the mapping operation is simply toList which collects the DataPoint objects of the same group into a list.

    Now we have a Map> and we want to convert it to a collection of DataSet objects. We simply stream out the map entries and construct DataSet objects, collect them into a list, and return it.

    The code ends up looking like this:

    Collection convertMultiDataPointToDataSet(List multiDataPoints) {
        return multiDataPoints.stream()
            .flatMap(mdp -> mdp.getData().entrySet().stream()
                               .map(e -> new KeyDataPoint(e.getKey(), mdp.getTimestamp(), e.getValue())))
            .collect(groupingBy(KeyDataPoint::getKey,
                        mapping(kdp -> new DataPoint(kdp.getTimestamp(), kdp.getData()), toList())))
            .entrySet().stream()
            .map(e -> new DataSet(e.getKey(), e.getValue()))
            .collect(toList());
    }
    

    I took some liberties with constructors and getters, but I think they should be obvious.

提交回复
热议问题