Gson 转换大数据内存不足错误

问题:当 processResul 数据量很大,比如有30万条数据时候,json转换不当会报内存不足错误。

下面是两种方式。

gson.fromJson 常规解析

Gson gson = new Gson();
for (int i = 0; i < data.length(); i++) {
    RecordDTO recordDTO = gson.fromJson(processResul, RecordDTO.class);
    resultList.add(recordDTO);
}

内存优化版


private Map<String, Pattern> cacheCompiledRegexPatterns() {
    Map<String, String> rawRegexMap = cacheRegexPatterns();
    return rawRegexMap.entrySet().stream()
      .collect(Collectors.toMap(Map.Entry::getKey, entry -> Pattern.compile(entry.getValue())));
}

private void processRecord(RecordDTO recordDTO, Map<String, Pattern> regexMap) {
    
    if (recordDTO == null) {
        return;
    }
    // 逻辑处理略
}

private void processInBatches(List<RecordDTO> resultList, Map<String, Pattern> regexMap) {
    if (resultList == null || resultList.isEmpty()) {
        return;
    }

    // 每批次处理的最大记录数
    final int batchSize = 1000;
    int totalSize = resultList.size();
    // 向上取整
    int numBatches = (totalSize + batchSize - 1) / batchSize;

    for (int batchIndex = 0; batchIndex < numBatches; batchIndex++) {
        int startIndex = batchIndex * batchSize;
        int endIndex = Math.min(startIndex + batchSize, totalSize);

        // 获取当前批次的数据
        List<RecordDTO> batch = resultList.subList(startIndex, endIndex);

        // 使用并行流处理批次中的每个记录
        batch.parallelStream().forEach(recordDTO -> processRecord(recordDTO, regexMap));
    }
}

private List<RecordDTO> parseJsonData(String processResul) {
    List<RecordDTO> resultList = new ArrayList<>();
    Gson gson = new Gson();

    try (JsonReader jsonReader = new JsonReader(new StringReader(processResul))) {
        jsonReader.beginObject();
        while (jsonReader.hasNext()) {
            String name = jsonReader.nextName();
            if ("data".equals(name) && jsonReader.peek() == JsonToken.BEGIN_ARRAY) {
                jsonReader.beginArray();
                while (jsonReader.hasNext()) {
                    try {
                        RecordDTO recordDTO = gson.fromJson(jsonReader, RecordDTO.class);
                        resultList.add(recordDTO);
                    } catch (Exception e) {
                        log.error("Error parsing JSON object in data array", e);
                    }
                }
                jsonReader.endArray();
            } else {
                jsonReader.skipValue();
            }
        }
        jsonReader.endObject();
    } catch (Exception e) {
        log.error("Error parsing JSON data", e);
    }

    return resultList;
}


public List<RecordDTO> queryFiles(FilesReq FilesReq){

    try {
        String processResul = HttpUtils.httpPostWithHeadersWithoutLoggingInterceptor(queryFilesUrl, params, headerMap);
        
        if (StringUtils.isNotEmpty(processResul)) {
            JSONObject jsonObject = new JSONObject(processResul);
            if (jsonObject.getInt("code") == 200) {
                Map<String, Pattern> regexMap = cacheCompiledRegexPatterns();
                List<RecordDTO> resultList = parseJsonData(processResul);
                processInBatches(resultList, regexMap);
                resultList.sort(Comparator.comparing(RecordDTO::getInvalidFile));
                return resultList;
            }
        }

    } catch (Exception e) {
        log.error("查询报错: ",e);
    }
    return Collections.emptyList();
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容