5分钟用Collectors.toMap构建数据转换原型

快速体验

  1. 打开 InsCode(快马)平台 https://www.inscode.net
  2. 输入框内输入如下内容:
    创建一个快速原型项目,展示如何用Collectors.toMap快速实现以下数据转换:1. CSV数据转内存Map;2. JSON数组转嵌套Map结构;3. 数据库查询结果转键值映射。要求:每个示例都能独立运行,使用最简代码结构,包含示例输入和预期输出。使用DeepSeek模型生成即用型代码片段。
  3. 点击'项目生成'按钮,等待项目生成完整后预览效果

示例图片

在日常开发中,我们经常需要将各种数据源转换为Map结构进行快速查询或处理。Java 8引入的Collectors.toMap方法,可以帮助我们用极简代码实现这种转换。今天我就通过三个常见场景,带大家体验如何用这个工具快速构建数据转换原型。

一、为什么选择Collectors.toMap?

  1. 代码简洁:相比传统循环填充Map的方式,流式操作+toMap往往只需1-2行代码
  2. 灵活性高:支持自定义键值生成逻辑,处理复杂转换游刃有余
  3. 原型友好:无需完整项目结构,单个方法即可验证数据处理逻辑

二、三大实战场景演示

场景1:CSV转内存Map

假设我们有一个简单的CSV字符串,需要将其转换为以第一列为键的Map:

  1. 原始数据示例:"id,name\n1,Apple\n2,Banana"
  2. 转换目标:{1="Apple", 2="Banana"}
  3. 关键步骤:按行分割→跳过标题行→拆分每列→收集为Map

这个原型特别适合处理配置文件或简单数据导入场景,5行代码就能完成从字符串到结构化数据的转换。

场景2:JSON数组转嵌套Map

现代应用经常需要处理JSON API响应,比如将用户列表按部门分组:

  1. 输入示例:[{"name":"张三","dept":"研发"},{"name":"李四","dept":"产品"}]
  2. 输出目标:{"研发"=["张三"], "产品"=["李四"]}
  3. 实现要点:使用groupingBy二次收集,构建多层映射关系

通过这个例子可以看到,toMap不仅能处理扁平数据,还能轻松构建复杂的数据结构。

场景3:数据库结果集转换

从数据库查询结果到内存映射是经典场景,假设查询得到用户记录:

  1. SQL结果:[(1,"Alice",25), (2,"Bob",30)]
  2. 转换需求:以ID为键,年龄为值{1=25, 2=30}
  3. 技巧点:ResultSet转流处理,注意空值情况的处理

这种转换在缓存预热或数据预加载时特别有用,避免了重复查询数据库。

三、原型开发经验分享

  1. 异常处理:记得处理重复键问题,toMap默认会抛IllegalStateException
  2. 性能注意:大数据集考虑使用并行流提升效率
  3. 调试技巧:在collect操作前插入peek()打印中间结果
  4. 链式组合:可以结合filter/map等操作实现更复杂的数据清洗

四、工具选择建议

最近发现InsCode(快马)平台特别适合快速验证这类数据转换想法。它的在线编辑器响应很快,内置的DeepSeek模型能直接生成可运行代码,省去了搭建本地环境的麻烦。

示例图片

最让我惊喜的是,写好转换逻辑后可以一键部署成可访问的API端点,方便与其他系统联调。比如上面的JSON转换例子,部署后就能直接通过URL测试转换效果,这对前后端协作太有帮助了。

示例图片

通过这次实践,我深刻体会到好的工具组合能让原型开发效率提升数倍。Collectors.toMap负责简化核心逻辑,InsCode提供即时的验证环境,这种工作流特别适合快速迭代的数据处理场景。

快速体验

  1. 打开 InsCode(快马)平台 https://www.inscode.net
  2. 输入框内输入如下内容:
    创建一个快速原型项目,展示如何用Collectors.toMap快速实现以下数据转换:1. CSV数据转内存Map;2. JSON数组转嵌套Map结构;3. 数据库查询结果转键值映射。要求:每个示例都能独立运行,使用最简代码结构,包含示例输入和预期输出。使用DeepSeek模型生成即用型代码片段。
  3. 点击'项目生成'按钮,等待项目生成完整后预览效果

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

请优化如下代码,并生成完整的代码, 使用springboot,如果用java处理tif请写出pom需要导入的包:public void generateAvgExp(String expName) { // 查询所有原型机的实验 List<GisDeviceInstance> deviceList = deviceInstanceMapper.selectList(Wrappers.<GisDeviceInstance>lambdaQuery().like(GisDeviceInstance::getName, "W")); List<Long> dIds = deviceList.stream().map(item -> item.getId()).distinct().collect(Collectors.toList()); List<GisExpRecord> expList = expRecordMapper.selectList(Wrappers.<GisExpRecord>lambdaQuery() .in(StrUtil.isEmpty(expName),GisExpRecord::getDeviceId, dIds) .eq(StrUtil.isNotEmpty(expName), GisExpRecord::getName,expName) .notIn(GisExpRecord::getExpType,new String[]{"5pdc6ly2ifo000", "4oxbk7okvsa000"}) ); // 依次处理每个实验 List<GisExpRecord> newExpList = expList.stream().map(exp -> handleAveExp(exp)).collect(Collectors.toList()); newExpList.forEach(exp -> { uploadFinished(exp.getId()); }); } private GisExpRecord handleAveExp(GisExpRecord exp) { String rootDir = configService.selectConfigByKey("gis.file.basePath"); List<GisDataOriginal> listEntity = new ArrayList<>(); // 复制并创建实验 String[] nArray = exp.getName().split("_"); String expName = StrUtil.format("{}_{}_{}_{}",nArray[0],nArray[1],"AVG",nArray[2]); GisExpRecord expEntity = expRecordMapper.selectOne(Wrappers.<GisExpRecord>lambdaQuery() .eq(GisExpRecord::getName,expName) .last("limit 1") ); if(ObjectUtil.isNotNull(expEntity)){ expRecordService.deleteWithValidByIds(ListUtil.of(expEntity.getId()),true); } BeanUtil.copyProperties(exp,expEntity); expEntity.setId(null); expEntity.setName(expName); expEntity.setCountInfo(new GisExpRecord.CountInfo(0,0,0,0)); expRecordMapper.insert(expEntity); // 源文件处理 数据平均&添加 List<GisDataOriginal> originals = baseMapper.selectList(Wrappers.<GisDataOriginal>lambdaQuery().eq(GisDataOriginal::getBizId, exp.getId())); Map<String, List<GisDataOriginal>> pointMap = originals.stream().collect(Collectors.groupingBy(item -> item.getNameValues().get("采样点"))); for(String point : pointMap.keySet()){ List<GisDataOriginal> sortedList = pointMap.get(point).stream().sorted(Comparator.comparing(item -> item.getNameValues().get("帧数"))).collect(Collectors.toList()); String endTime = sortedList.get(sortedList.size() - 1).getNameValues().get("结束时间"); String newName = sortedList.get(0).getName().replace(sortedList.get(0).getNameValues().get("结束时间"),endTime); List<String> tifPths = sortedList.stream().map(item -> Paths.get(rootDir,item.getPath(), item.getName() + "." + item.getSuffix()).toString()).collect(Collectors.toList()); String tifArgs = CollUtil.join(tifPths,","); Path storeDir = Paths.get(rootDir, "raw_data", String.valueOf(expEntity.getId())); if(!FileUtil.file(storeDir.toString()).exists()){ FileUtil.mkdir(storeDir); } String savePth = Paths.get(storeDir.toString(), newName+ ".tif").toString(); PythonUtil.exec(SCRIPT_AVG_PTH,"--tif_list",tifArgs,"--save_pth",savePth); // 添加平均后的tif if(FileUtil.file(savePth).exists()){ GisDataOriginal avgOriginal = new GisDataOriginal(); BeanUtil.copyProperties(sortedList.get(0),avgOriginal); avgOriginal.setId(null); avgOriginal.setName(newName); avgOriginal.setBizId(expEntity.getId()); avgOriginal.setPath("raw_data/"+expEntity.getId() + "/"); avgOriginal.setSize(new BigDecimal(String.valueOf(FileUtil.size(FileUtil.file(savePth))))); avgOriginal.getNameValues().put("结束时间",endTime); listEntity.add(avgOriginal); } } if(CollUtil.isNotEmpty(listEntity)){ baseMapper.insertBatch(listEntity); } // 指标数据处理 List<GisDataIndicator> saveIndicatorList = new ArrayList<>(); List<GisDataIndicator> indicatorList = indicatorMapper.selectList(Wrappers.<GisDataIndicator>lambdaQuery().eq(GisDataIndicator::getExpId, exp.getId())); for (GisDataIndicator item : indicatorList){ GisDataIndicator save = new GisDataIndicator(); BeanUtil.copyProperties(item,save); save.setId(null); save.setExpId(expEntity.getId()); saveIndicatorList.add(save); } if(CollUtil.isNotEmpty(saveIndicatorList)){ indicatorMapper.insertBatch(saveIndicatorList); } return expEntity; }
11-20
对于以下方式创建的bean: ```java @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) @Documented public @interface IgnoreUrlOrder { int value() default LOWEST_PRECEDENCE; /** * Useful constant for the highest precedence value. * @see java.lang.Integer#MIN_VALUE */ int HIGHEST_PRECEDENCE = Integer.MAX_VALUE; /** * Useful constant for the lowest precedence value. * @see java.lang.Integer#MAX_VALUE */ int LOWEST_PRECEDENCE = Integer.MIN_VALUE; } @EnableConfigurationProperties(XmlIgnoreUrlScannerProperties.class) public class DefaultIgnoreUrlAutoConfiguration { @Bean @IgnoreUrlOrder(IgnoreUrlOrder.HIGHEST_PRECEDENCE) protected IgnoreUrlRule apiIgnoreUrlRule(RequestMappingHandlerMapping requestMappingHandlerMapping){ return ApiIgnoreUrlScanner.scan(requestMappingHandlerMapping); } @Bean @IgnoreUrlOrder(IgnoreUrlOrder.HIGHEST_PRECEDENCE-1) protected IgnoreUrlRule xmlIgnoreUrlRule(XmlIgnoreUrlScannerProperties fileScanProperties) { return IgnoreUrlRule.builder() .strategy(IgnoreUrlRuleStrategy.LAST_WINS) .patterns(XmlIgnoreUrlScanner.scan(fileScanProperties).stream().map(e -> IgnoreUrlPattern.builder().url(e.get("path")).method(e.get("method")).build()).toList()) .build(); } } ``` 请通过合适的方式,在已经获取了 List<IgnoreUrlRule> 的前提下: 1. 使用spring boot 3.5.5 2. 获取每个 IgnoreUrlRule bean对象上的 IgnoreUrlOrder 注解 3. 没有使用 IgnoreUrlOrder 注解的 IgnoreUrlRule bean 使用默认值 4. 对 List<IgnoreUrlRule> 进行排序,排序规则如下: 1). 优先对没有 IgnoreUrlOrder 注解的 IgnoreUrlRule 按照bean name的字典顺序从小大排序 2). 然后对有 IgnoreUrlOrder 注解的 IgnoreUrlRule 按照IgnoreUrlOrder的约定从小大排序
09-23
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

StarfallRaven13

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值