如何高效将指定文件夹下多份JSON文件读取合并至单个Map?
嘿,我来帮你搞定多JSON文件合并到单个Map的问题!你已经有了单文件的读取逻辑,接下来只需要扩展成批量处理就行,而且可以做得很高效。下面是具体的实现方案:
高效处理多JSON文件合并到单个Map的方案
1. 先获取目标文件夹下的所有JSON文件
首先得拿到指定文件夹里的所有.json文件。如果是ClassPath下的文件夹(比如项目resources目录里的文件夹,或者打包后jar包里的资源),推荐用Spring的ResourcePatternResolver来扫描,它能兼容文件系统和jar包内的资源:
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); // 替换成你的文件夹路径,**/*.json表示递归扫描所有子文件夹里的JSON文件 Resource[] resources = resolver.getResources("classpath:your-target-folder/**/*.json");
如果是本地文件系统的文件夹(非ClassPath),可以用Files.walk来遍历:
Path folderPath = Paths.get("/your/local/folder/path"); List<Path> jsonFiles = Files.walk(folderPath) .filter(Files::isRegularFile) .filter(path -> path.toString().endsWith(".json")) .collect(Collectors.toList());
2. 串行读取并合并到Map(基础高效版)
初始化一个目标Map,然后遍历每个资源文件,读取后合并进去。这里有几个关键的效率优化点:
- 复用ObjectMapper:不要每次读取都新建ObjectMapper,它的创建成本很高,全局复用一个实例能大幅提升性能
- 用try-with-resources自动关流:避免InputStream资源泄漏
// 初始化目标Map,HashMap足够应对大部分场景 Map<String, MappedContacts> combinedMap = new HashMap<>(); // 复用这个ObjectMapper实例,不要在循环里new ObjectMapper objectMapper = new ObjectMapper(); for (Resource resource : resources) { try (InputStream input = resource.getInputStream()) { // 读取单个文件的Map Map<String, MappedContacts> jsonMap = objectMapper.readValue( input, new TypeReference<Map<String, MappedContacts>>() {} ); // 直接合并到总Map,若有重复key,后面的会覆盖前面的 combinedMap.putAll(jsonMap); // 如果你需要自定义重复key的处理逻辑(比如合并字段),可以改成: // jsonMap.forEach((key, value) -> combinedMap.merge(key, value, (oldVal, newVal) -> { // // 示例:合并两个MappedContacts的某个字段 // oldVal.setContactCount(oldVal.getContactCount() + newVal.getContactCount()); // return oldVal; // })); } catch (IOException e) { // 根据业务需求处理异常,比如打印日志或抛出自定义异常 throw new RuntimeException("读取JSON文件失败:" + resource.getFilename(), e); } }
3. 并行处理提升效率(适合大量/大文件场景)
如果你的JSON文件数量多、单文件体积大,串行处理慢的话,可以用并行流来加速。但要注意线程安全,改用ConcurrentHashMap作为目标Map:
// 用ConcurrentHashMap保证并行操作时的线程安全 Map<String, MappedContacts> combinedMap = new ConcurrentHashMap<>(); ObjectMapper objectMapper = new ObjectMapper(); Arrays.stream(resources) .parallel() // 开启并行流 .forEach(resource -> { try (InputStream input = resource.getInputStream()) { Map<String, MappedContacts> jsonMap = objectMapper.readValue( input, new TypeReference<Map<String, MappedContacts>>() {} ); // 并行环境下安全合并 combinedMap.putAll(jsonMap); // 同样,自定义重复key逻辑用merge: // jsonMap.forEach((key, value) -> combinedMap.merge(key, value, (oldVal, newVal) -> { // // 自定义合并逻辑 // return oldVal; // })); } catch (IOException e) { throw new RuntimeException("读取JSON文件失败:" + resource.getFilename(), e); } });
⚠️ 注意:如果文件数量少、体积小,并行处理反而可能因为线程切换开销变慢,这种情况用串行更合适。
4. 关键注意事项
- 永远复用ObjectMapper:这是提升效率的核心,ObjectMapper的初始化涉及大量配置和缓存,重复创建会浪费资源
- 处理重复key:提前明确业务规则——遇到重复key是覆盖、合并还是抛出异常,避免后续出现数据问题
- ClassPath资源兼容性:如果资源在jar包里,不要用
File类读取,必须用Resource相关API,否则会找不到文件
内容的提问来源于stack exchange,提问作者redAce
相关产品推荐
相关产品推荐

