Spring 6中如何将Properties文件高效转换为HashMap<String, Identity>
将分层Properties文件转换为HashMap<String, Identity>
问题背景
现有如下结构的Properties文件:
abc.name = John abc.id = 1234 abc.dep = sales bac.name = Jen bac.id = 3422 bac.dep = marketing
需要转换为键为abc、bac,值为Identity对象的HashMap<String, Identity>,Identity类定义如下:
public class Identity{ private String name; private Long id; private String dep; // 需补充getter、setter方法 }
目前通过读取文件、遍历键拆分、computeIfAbsent结合switch语句实现,想知道有没有更简洁的实现方式或可用工具库。
解决方案
1. 优化原生Java写法(无额外依赖)
不用switch语句,而是用映射表关联属性名和对象赋值逻辑,代码更简洁易维护:
import java.io.FileInputStream; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.function.BiConsumer; public class PropertiesToMapConverter { public static void main(String[] args) throws Exception { Properties props = new Properties(); props.load(new FileInputStream("your.properties")); Map<String, Identity> identityMap = new HashMap<>(); // 定义属性名到Identity赋值逻辑的映射 Map<String, BiConsumer<Identity, String>> propertyHandlers = Map.of( "name", Identity::setName, "id", (identity, val) -> identity.setId(Long.parseLong(val)), "dep", Identity::setDep ); props.forEach((keyObj, valueObj) -> { String key = (String) keyObj; String value = (String) valueObj; String[] keyParts = key.split("\\.", 2); if (keyParts.length != 2) return; String prefix = keyParts[0]; String property = keyParts[1]; // 不存在则创建新Identity,然后执行赋值逻辑 Identity identity = identityMap.computeIfAbsent(prefix, k -> new Identity()); propertyHandlers.getOrDefault(property, (i, v) -> {}).accept(identity, value); }); } }
2. 借助工具库简化实现
如果项目允许引入第三方库,有两个常用选择:
Apache Commons Configuration
这个库天生支持分层属性结构,能直接按前缀提取属性组:
import org.apache.commons.configuration2.PropertiesConfiguration; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; public class CommonsConfigConverter { public static void main(String[] args) throws Exception { PropertiesConfiguration config = new PropertiesConfiguration("your.properties"); Map<String, Identity> identityMap = new HashMap<>(); // 提取所有顶层前缀(abc、bac) Set<String> topPrefixes = config.getKeys().stream() .map(k -> k.split("\\.", 2)[0]) .collect(Collectors.toSet()); for (String prefix : topPrefixes) { Identity identity = new Identity(); identity.setName(config.getString(prefix + ".name")); identity.setId(config.getLong(prefix + ".id")); identity.setDep(config.getString(prefix + ".dep")); identityMap.put(prefix, identity); } } }
需要引入Maven依赖:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-configuration2</artifactId> <version>2.8.0</version> </dependency>
Spring Boot ConfigurationProperties(Spring项目专属)
如果是Spring Boot项目,用注解就能自动完成映射,几乎不用写代码:
- 定义配置类:
import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.Map; @ConfigurationProperties(prefix = "") // 空前缀匹配顶层的abc、bac public class IdentityConfig { private Map<String, Identity> identities; // getter、setter public Map<String, Identity> getIdentities() { return identities; } public void setIdentities(Map<String, Identity> identities) { this.identities = identities; } // 内部类对应Identity结构 public static class Identity { private String name; private Long id; private String dep; // getter、setter public String getName() { return name; } public void setName(String name) { this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getDep() { return dep; } public void setDep(String dep) { this.dep = dep; } } }
- 在配置类或启动类上开启属性绑定:
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; @Configuration @EnableConfigurationProperties(IdentityConfig.class) public class AppConfig { }
之后直接注入IdentityConfig就能拿到映射好的Map<String, Identity>。
内容的提问来源于stack exchange,提问作者Rajib Sharma
相关产品推荐
相关产品推荐

