如何将 Java 对象递归扁平化为键值对映射

来源:建站作者:厦门程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《如何将 Java 对象递归扁平化为键值对映射》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何将 Java 对象递归扁平化为键值对映射》有用,将其分享出去将是对创作者最好的鼓励。

在Java开发中,我们经常会遇到需要将复杂的嵌套对象转换为扁平键值对映射的场景,比如将实体类对象转换为适合存储到Redis的Map结构,或者将配置类的嵌套属性转换为统一的配置键值对。递归扁平化可以自动处理对象的多层嵌套结构,无需手动逐层解析属性,大幅提升开发效率。

如何将 Java 对象递归扁平化为键值对映射

核心实现思路

要实现Java对象的递归扁平化,首先需要明确处理的对象类型和转换规则:

  • 对于基础类型、包装类型、字符串等简单属性,直接将其属性名作为键,属性值作为值存入映射
  • 对于自定义对象类型的属性,需要递归处理该对象的属性,键名拼接当前属性名和子属性名,用分隔符连接
  • 对于集合、数组类型的属性,需要遍历每个元素,键名拼接当前属性名和元素索引,再递归处理元素内容
  • 对于Map类型的属性,需要遍历每个键值对,键名拼接当前属性名和Map的键,再递归处理Map的值

基础工具类实现

下面是一个通用的递归扁平化工具类,支持处理上述多种属性类型,默认使用点号作为键名分隔符:

import java.lang.reflect.Field;
import java.util.*;

public class ObjectFlattener {

    private static final String DEFAULT_SEPARATOR = ".";

    /**
     * 将对象递归扁平化为键值对映射
     * @param obj 待转换的对象
     * @return 扁平化后的Map
     */
    public static Map<String, Object> flatten(Object obj) {
        Map<String, Object> result = new HashMap<>();
        if (obj == null) {
            return result;
        }
        // 处理基础类型、包装类型、字符串等简单类型
        if (isSimpleType(obj.getClass())) {
            result.put("", obj);
            return result;
        }
        // 处理Map类型
        if (obj instanceof Map) {
            flattenMap((Map<?, ?>) obj, "", result, DEFAULT_SEPARATOR);
            return result;
        }
        // 处理数组类型
        if (obj.getClass().isArray()) {
            flattenArray(obj, "", result, DEFAULT_SEPARATOR);
            return result;
        }
        // 处理集合类型
        if (obj instanceof Collection) {
            flattenCollection((Collection<?>) obj, "", result, DEFAULT_SEPARATOR);
            return result;
        }
        // 处理自定义对象类型
        flattenObject(obj, "", result, DEFAULT_SEPARATOR);
        return result;
    }

    /**
     * 判断是否为简单类型
     */
    private static boolean isSimpleType(Class<?> clazz) {
        return clazz.isPrimitive() 
                || clazz.equals(String.class)
                || clazz.equals(Integer.class)
                || clazz.equals(Long.class)
                || clazz.equals(Double.class)
                || clazz.equals(Float.class)
                || clazz.equals(Boolean.class)
                || clazz.equals(Character.class)
                || clazz.equals(Byte.class)
                || clazz.equals(Short.class)
                || clazz.equals(Date.class);
    }

    /**
     * 递归处理自定义对象
     */
    private static void flattenObject(Object obj, String prefix, Map<String, Object> result, String separator) {
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object value = field.get(obj);
                String key = prefix.isEmpty() ? field.getName() : prefix + separator + field.getName();
                processValue(value, key, result, separator);
            } catch (IllegalAccessException e) {
                // 忽略无法访问的属性
            }
        }
    }

    /**
     * 递归处理Map类型
     */
    private static void flattenMap(Map<?, ?> map, String prefix, Map<String, Object> result, String separator) {
        for (Map.Entry<?, ?> entry : map.entrySet()) {
            String key = prefix.isEmpty() ? entry.getKey().toString() : prefix + separator + entry.getKey().toString();
            processValue(entry.getValue(), key, result, separator);
        }
    }

    /**
     * 递归处理数组类型
     */
    private static void flattenArray(Object array, String prefix, Map<String, Object> result, String separator) {
        int length = java.lang.reflect.Array.getLength(array);
        for (int i = 0; i < length; i++) {
            Object value = java.lang.reflect.Array.get(array, i);
            String key = prefix + separator + i;
            processValue(value, key, result, separator);
        }
    }

    /**
     * 递归处理集合类型
     */
    private static void flattenCollection(Collection<?> collection, String prefix, Map<String, Object> result, String separator) {
        int index = 0;
        for (Object item : collection) {
            String key = prefix + separator + index;
            processValue(item, key, result, separator);
            index++;
        }
    }

    /**
     * 处理属性值,根据类型选择不同的处理逻辑
     */
    private static void processValue(Object value, String key, Map<String, Object> result, String separator) {
        if (value == null) {
            result.put(key, null);
            return;
        }
        Class<?> clazz = value.getClass();
        if (isSimpleType(clazz)) {
            result.put(key, value);
        } else if (value instanceof Map) {
            flattenMap((Map<?, ?>) value, key, result, separator);
        } else if (clazz.isArray()) {
            flattenArray(value, key, result, separator);
        } else if (value instanceof Collection) {
            flattenCollection((Collection<?>) value, key, result, separator);
        } else {
            flattenObject(value, key, result, separator);
        }
    }
}

使用示例

假设我们有如下嵌套的实体类结构:

class User {
    private String name;
    private Integer age;
    private Address address;
    private List<String> hobbies;
    private Map<String, String> extraInfo;

    // 省略构造方法、getter、setter
}

class Address {
    private String province;
    private String city;
    private String street;

    // 省略构造方法、getter、setter
}

创建对象并调用扁平化工具类:

public class Test {
    public static void main(String[] args) {
        User user = new User();
        user.setName("张三");
        user.setAge(25);
        
        Address address = new Address();
        address.setProvince("广东");
        address.setCity("深圳");
        address.setStreet("科技园路");
        user.setAddress(address);
        
        List<String> hobbies = new ArrayList<>();
        hobbies.add("篮球");
        hobbies.add("阅读");
        user.setHobbies(hobbies);
        
        Map<String, String> extraInfo = new HashMap<>();
        extraInfo.put("job", "程序员");
        extraInfo.put("level", "中级");
        user.setExtraInfo(extraInfo);
        
        Map<String, Object> flatMap = ObjectFlattener.flatten(user);
        for (Map.Entry<String, Object> entry : flatMap.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
    }
}

输出结果如下:

name : 张三
age : 25
address.province : 广东
address.city : 深圳
address.street : 科技园路
hobbies.0 : 篮球
hobbies.1 : 阅读
extraInfo.job : 程序员
extraInfo.level : 中级

注意事项

  • 上述实现使用反射获取对象属性,无法处理父类的属性,如果需要支持父类属性,可以修改获取字段的逻辑,遍历所有父类的字段
  • 如果对象中存在循环引用,递归处理会导致栈溢出,需要根据实际需求添加循环引用检测逻辑
  • 默认分隔符是点号,如果需要使用其他分隔符,可以扩展工具类的方法,支持自定义分隔符参数
  • 对于静态属性、final属性等特殊情况,上述代码没有做特殊处理,实际使用时可以根据需求调整反射获取字段的逻辑

Java递归扁平化键值对映射对象转换修改时间:2026-06-26 03:06:35

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。