使用Java流的复杂对象组列表 [英] group list of complex object using java stream

查看:98
本文介绍了使用Java流的复杂对象组列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个gprsEvents列表,其中列表中的每个元素都是Map< String,Object>.如下所示.我需要:

I have a list of gprsEvents where each element in the list is a Map<String,Object> as shown below. I need to:

{
   "events":[
      {
         "localTimeStamp":"20170523113305",
         "serviceCode":"GPRS",
         "recEntityCode":[
            "1",
            "2"
         ],
         "index":"1",
         "dataVolumeIncoming":"400000",
         "dataVolumeOutgoing":"27600",
         "callChargingId":"4100853125",
      },
      {
         "localTimeStamp":"20190523113305",
         "serviceCode":"GPRS",
         "recEntityCode":[
            "2",
            "4"
         ],
         "index":"2",
         "dataVolumeIncoming":"300000",
         "dataVolumeOutgoing":"47600",
         "callChargingId":"4100853125",
      },
      {
         "localTimeStamp":"20180523113305",
         "serviceCode":"GPRS",
         "recEntityCode":[
            "1",
            "2"
         ],
         "index":"7",
         "dataVolumeIncoming":"100000",
         "dataVolumeOutgoing":"17600",
         "callChargingId":"5100853125",
      }
      
   ]
}

  1. 通过"callChargingId"字段将列表中的元素分组.
  2. 分组的结果应该是一个Map,其中键是"callChargingIds",是一个单个元素,其中每个字段包含作为分组结果的一组字段.结果应该如下所示:
  1. group elements in the list by the field "callChargingId".
  2. the result of the grouping should be a Map where the keys are the "callChargingIds", be one single element, where each of the fields containing a Set of fields as result of the grouping. The result should be as you can see below:

{
   "5100853125":[
      {
         "localTimeStamp":"20180523113305",
         "serviceCode":"GPRS",
         "recEntityCode":[
            "1",
            "2"
         ],
         "index":"7",
         "dataVolumeIncoming":"100000",
         "dataVolumeOutgoing":"17600"
      }
   ],
   "4100853125":[
      {
         "localTimeStamp":[
            "20170523113305",
            "20190523113305"
         ],
         "serviceCode":"GPRS",
         "recEntityCode":[
            [
               "1",
               "2"
            ],
            [
               "2",
               "4"
            ]
         ],
         "index":[
            "1",
            "2"
         ],
         "dataVolumeIncoming":"700000",
         "dataVolumeOutgoing":"75200"
      }
   ]
}

对于某些字段,分组的结果应为列表(timeStamp,recEntityCode和index),而在其他字段中,结果应为求和值(dataVolumeIncoming和dataVolumeOutgoing

where for some fields the result of the grouping should be a list (timeStamp, recEntityCode and index), and in other fields the result should be the summe (dataVolumeIncoming and dataVolumeOutgoing

我开始考虑使用Java 8流(groupingBy): gprsEvents.stream().collect(Collectors.groupingBy(map-> map.get("callChargingId").toString()))

I started thinking about using java 8 stream (groupingBy): gprsEvents.stream().collect(Collectors.groupingBy(map -> map.get("callChargingId").toString()))

我现在特别想获得合适的结果,以便将结果得到一张地图以及上述字段的列表或总和...

I'm now stuck to get suitable result specially to get the result in one single Map and the list or sum of the above mentioned fields...

推荐答案

此处的重点是实现BinaryOperator<U> mergeFunction对象,该对象将完成最复杂的部分:合并两个Map实例.我建议使用带有3个参数的方法:

Key point here is to implement BinaryOperator<U> mergeFunction object which will do the most complex part: merging two Map instances. I suggest to use a method with 3 parameters: toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator mergeFunction):

  1. keyMapper-callChargingId值,
  2. valueMapper-Map实例
  3. mergeFunction-合并将合并两个BinaryOperator<Map<String, Object>>
  4. 类型的实例
  1. keyMapper - callChargingId value,
  2. valueMapper - Map instance
  3. mergeFunction - merger which will merge two instances of type BinaryOperator<Map<String, Object>>

简单的实现可能看起来像这样:

Simple implementation could look like this:

import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.type.MapType;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;

public class JsonTypeInfoApp {
    public static void main(String[] args) throws IOException {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        JsonMapper mapper = JsonMapper.builder()
                .enable(SerializationFeature.INDENT_OUTPUT)
                .build();
        MapType jsonType = mapper.getTypeFactory().constructMapType(Map.class, String.class, List.class);
        Map<String, List<Map<String, Object>>> response = mapper.readValue(jsonFile, jsonType);

        List<Map<String, Object>> gprsEvents = response.get("events");
        Map<Object, Map<String, Object>> result = gprsEvents.stream()
                .collect(Collectors.toMap(
                        map -> map.get("callChargingId"),
                        map -> map,
                        new EventMerger()));

        mapper.writeValue(System.out, result);
    }
}

class EventMerger implements BinaryOperator<Map<String, Object>> {

    @Override
    public Map<String, Object> apply(Map<String, Object> map0, Map<String, Object> map1) {
        map1.forEach((secondKey, secondValue) -> {
            map0.compute(secondKey, (key, value) -> {
                if (value == null) {
                    return secondValue;
                } else if (value instanceof Set) {
                    Set<Object> values = (Set<Object>) value;
                    values.add(secondValue);
                    return values;
                }

                Set<Object> values = new HashSet<>();
                values.add(value);
                values.add(secondValue);

                return values;
            });
        });
        return map0;
    }
}

上面的代码显示:

{
  "4100853125" : {
    "localTimeStamp" : [ "20170523113305", "20190523113305" ],
    "serviceCode" : [ "GPRS" ],
    "recEntityCode" : [ [ "1", "2" ], [ "2", "4" ] ],
    "index" : [ "1", "2" ],
    "dataVolumeOutgoing" : [ "47600", "27600" ],
    "callChargingId" : [ "4100853125" ],
    "dataVolumeIncoming" : [ "400000", "300000" ]
  },
  "5100853125" : {
    "localTimeStamp" : "20180523113305",
    "serviceCode" : "GPRS",
    "recEntityCode" : [ "1", "2" ],
    "index" : "7",
    "dataVolumeIncoming" : "100000",
    "dataVolumeOutgoing" : "17600",
    "callChargingId" : "5100853125"
  }
}

这篇关于使用Java流的复杂对象组列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆