当前位置: 首页 > 知识库问答 >
问题:

使用java流的复杂对象组列表

周志文
2023-03-14

我有一个gprsEvents列表,其中列表中的每个元素都是一个映射 ,如下所示。我需要:

{
   "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",
      }
      
   ]
}
    null
{
   "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"
      }
   ]
}

我开始考虑使用Java8Stream(groupingBy):gprsents.stream().collectors.groupingBy(Map->map.Get(“CallChargingID”).ToString()))

我现在坚持得到合适的结果,特别是在一个单一的地图和上面提到的字段的列表或总和的结果...

共有1个答案

宇文修筠
2023-03-14

这里的关键是实现BinaryOperatorMergeFunction对象,它将完成最复杂的部分:合并两个Map实例。我建议使用具有3个参数的方法:toMap(函数<?super T,?extends k>keyMapper,函数<?super T,?extends u>valueMapper,BinaryOperator mergeFunction):

  1. KeyMapper-CallChargingID值,
  2. valueMapper-映射实例
  3. MergeFunction-合并,它将合并BinaryOperator >
  4. 类型的两个实例

简单的实现可能如下所示:

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流来解决这个问题: 有什么解决办法吗?谢谢!

  • 我有一个Web Api 2项目,它有一个HttpGet方法,该方法将复杂对象的列表作为参数。像这样: 我用swashbuckle来设置我的swagger文档。但是它像这样设置这个参数: 至少对象似乎需要一些东西。 后来在定义部分我确实发现了这一点: 但它似乎没有被使用... 有没有办法设置它,让swagger理解这是一个对象列表,并给我一种为各个属性输入值的方法?(就像我对不是列表的复杂对象所做的

  • 我试图从一个相当复杂的Java对象生成一个CSV文件。该对象是一个会话,具有一些属性,字符串和消息的列表,这些字符串和消息又具有一些属性,还有一个注释的列表,这些注释具有一些属性。 session类如下所示; 消息类如下所示; 事实上,开始认为(单一的)CSV可能不是解决这个问题的最佳方法。

  • 我得到和错误当我执行 错误是: 未处理的异常:com.google.gson.JsonSyntaxException:java.lang.IllegalStateException:预期BEGIN_OBJECT但BEGIN_ARRAY在第1行第52列路径$. f 这是 json 响应 我有这个班级 和这个其他