问题:当 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();
}