从反射到switch case手写set 再到BiConsumer优化service层代码逻辑
比如下面这段原始反射代码,QmApResultsDetailDataExportDTO 大概有一百个属性,为了赋值方便用反射给属性赋值,这里不是一个元素的属性赋值,而是从库中查出100条数据,每条数据的一百个元素都要赋值,反射会执行一万次,由于反射赋值非常慢,出现性能问题。
为什么反射会慢:方法查找:getDeclaredMethod 需要遍历类的所有方法 ,访问检查:setAccessible(true) 有开销,安全检查:每次调用都进行权限验证
for (QmApDataSourceNameDTO sourceNameDTO : sourceNameDTOS) { String prop = NumberToLetterConverter.convertToLetters(sourceNameDTO.getSourcePkid());//pkid是数字,转成字符串做属性 try { Field field = QmApResultsDetailDataExportDTO.class.getDeclaredField(prop); field.setAccessible(true); // 私有属性需要设置可访问 field.set(exportDTO, sourceNameDTO.getValue()); } catch (Exception e) { throw new RuntimeException(e); } }
如果是写框架,不知道类型,可以用反射,这种应用代码尽量不要用反射。
改成手写set后
List<String> pkidList = list.stream().map(e->e.getPkid()).collect(Collectors.toList()); List<QmApDataSourceNameDTO> dataSourceNameDTOList = resultsDetailsMapper.queryDataSourceNames2(pkidList); for (QmApResultsDetailDataExportDTO exportDTO : list) { List<QmApDataSourceNameDTO> filterDataSourceNameDTOList = dataSourceNameDTOList.stream().filter(e->e.getPkid().equals(exportDTO.getPkid())).collect(Collectors.toList()); for (QmApDataSourceNameDTO qmApDataSourceNameDTO : filterDataSourceNameDTOList) { String sourcePkid = qmApDataSourceNameDTO.getSourcePkid(); switch (sourcePkid) { case "1000000": exportDTO.setBaaaaaa(qmApDataSourceNameDTO.getValue()); exportDTO.setBaaaaaaScore(qmApDataSourceNameDTO.getScore()); break; case "1002008": exportDTO.setBaacaai(qmApDataSourceNameDTO.getValue()); exportDTO.setBaacaaiScore(qmApDataSourceNameDTO.getScore()); break;
这种循环list,每次从大list(dataSourceNameDTOList)中filter一个小结果集,可以优化成把大list按过滤的逻辑分组,避免每次循环都filter一次。switch case太多的情况下可以换成BiConsumer,将赋值
逻辑放到BiConsumer中。
优化后的代码
// 优化:按pkid分组,避免多次遍历整个列表 Map<String, List<QmApDataSourceNameDTO>> groupedDataSourceMap = dataSourceNameDTOList.stream() .collect(Collectors.groupingBy(QmApDataSourceNameDTO::getPkid)); // 使用Map替代switch-case,提高可维护性和性能 Map<String, BiConsumer<QmApResultsDetailDataExportDTO, QmApDataSourceNameDTO>> propertySetters = new HashMap<>(); initializePropertySetters(propertySetters); for (QmApResultsDetailDataExportDTO exportDTO : list) { List<QmApDataSourceNameDTO> filterDataSourceNameDTOList = groupedDataSourceMap.getOrDefault(exportDTO.getPkid(), Collections.emptyList()); for (QmApDataSourceNameDTO qmApDataSourceNameDTO : filterDataSourceNameDTOList) { String sourcePkid = qmApDataSourceNameDTO.getSourcePkid(); BiConsumer<QmApResultsDetailDataExportDTO, QmApDataSourceNameDTO> setter = propertySetters.get(sourcePkid); if (setter != null) { setter.accept(exportDTO, qmApDataSourceNameDTO); } } }
private void initializePropertySetters(Map<String, BiConsumer<QmApResultsDetailDataExportDTO, QmApDataSourceNameDTO>> propertySetters) {
propertySetters.put("1000000", (dto, data) -> {
dto.setBaaaaaa(data.getValue());
dto.setBaaaaaaScore(data.getScore());
});
propertySetters.put("1002008", (dto, data) -> {
dto.setBaacaai(data.getValue());
dto.setBaacaaiScore(data.getScore());
});
浙公网安备 33010602011771号