如何在java中合并两个复杂的对象 [英] How to merge two complex objects in java

查看:151
本文介绍了如何在java中合并两个复杂的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个java对象,我想将它们合并到单个对象中。问题是两个对象不包含普通原始类型属性(字段),它们包含复杂类型属性(如其他类型的对象和其他类型的对象列表)。

I have two java objects and I want to merge them into single object. Problem is the two objects does not contain plain primitive type properties(fields) they contain complex type properties(like object of other type and list of objects of other type).

对象1:通过设置一些属性(字段)返回和

Object 1: Returns by setting up some properties (fields) and

对象2:通过设置返回某些属性(字段)或者它可能返回它所持有的类型的新对象但不会被对象1返回。

Objects 2: returns by setting up some properties (fields) or it may return new objects of the type which it holds but not returned by object 1.

对象1和对象2都是相同的类型。

Both object 1 and object 2 are of same type.

结果对象3 = obj1属性+如果类型与obj1相同,则更新obj 2中的属性+来自obj2的新更新对象

Result Object 3 = obj1 properties + update the properties from obj 2 if same type as obj1 + new updated object from obj2

推荐答案

使用spring提供的 org.springframework.beans.BeanUtils 类非常容易。或者 Apache Commons BeanUtils库,我相信Springs版本要么是基于或与之相同。

Its pretty easy to do using the org.springframework.beans.BeanUtils class provided by spring. Or the Apache Commons BeanUtils library which I believe Springs version is either based on or is the same as.

public static <T> T combine2Objects(T a, T b) throws InstantiationException, IllegalAccessException {
    // would require a noargs constructor for the class, maybe you have a different way to create the result.
    T result = (T) a.getClass().newInstance();
    BeanUtils.copyProperties(a, result);
    BeanUtils.copyProperties(b, result);
    return result;
}

如果你不能或没有noargs构造函数你可能只是传递结果

if you cant or dont have a noargs constructor maybe you just pass in the result

public static <T> T combine2Objects(T a, T b, T destination) {
    BeanUtils.copyProperties(a, destination);
    BeanUtils.copyProperties(b, destination);
    return destination;
}






如果你不想要null正在复制的属性可以使用以下内容:


If you dont want null properties being copied you can use something like this:

public static void nullAwareBeanCopy(Object dest, Object source) throws IllegalAccessException, InvocationTargetException {
    new BeanUtilsBean() {
        @Override
        public void copyProperty(Object dest, String name, Object value)
                throws IllegalAccessException, InvocationTargetException {
            if(value != null) {
                super.copyProperty(dest, name, value);
            }
        }
    }.copyProperties(dest, source);
}






嵌套对象解决方案

这是一个更强大的解决方案。它支持嵌套对象复制,不再通过引用复制1+级别的对象,而是克隆嵌套对象或单独复制其属性。

Heres a bit more robust solution. It supports nested object copying, objects 1+ level deep will no longer be copied by reference, instead Nested objects will be cloned or their properties be copied individually.

/**
 * Copies all properties from sources to destination, does not copy null values and any nested objects will attempted to be
 * either cloned or copied into the existing object. This is recursive. Should not cause any infinite recursion.
 * @param dest object to copy props into (will mutate)
 * @param sources
 * @param <T> dest
 * @return
 * @throws IllegalAccessException
 * @throws InvocationTargetException
 */
public static <T> T copyProperties(T dest, Object... sources) throws IllegalAccessException, InvocationTargetException {
    // to keep from any chance infinite recursion lets limit each object to 1 instance at a time in the stack
    final List<Object> lookingAt = new ArrayList<>();

    BeanUtilsBean recursiveBeanUtils = new BeanUtilsBean() {

        /**
         * Check if the class name is an internal one
         * @param name
         * @return
         */
        private boolean isInternal(String name) {
            return name.startsWith("java.") || name.startsWith("javax.")
                    || name.startsWith("com.sun.") || name.startsWith("javax.")
                    || name.startsWith("oracle.");
        }

        /**
         * Override to ensure that we dont end up in infinite recursion
         * @param dest
         * @param orig
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         */
        @Override
        public void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException {
            try {
                // if we have an object in our list, that means we hit some sort of recursion, stop here.
                if(lookingAt.stream().anyMatch(o->o == dest)) {
                    return; // recursion detected
                }
                lookingAt.add(dest);
                super.copyProperties(dest, orig);
            } finally {
                lookingAt.remove(dest);
            }
        }

        @Override
        public void copyProperty(Object dest, String name, Object value)
                throws IllegalAccessException, InvocationTargetException {
            // dont copy over null values
            if (value != null) {
                // attempt to check if the value is a pojo we can clone using nested calls
                if(!value.getClass().isPrimitive() && !value.getClass().isSynthetic() && !isInternal(value.getClass().getName())) {
                    try {
                        Object prop = super.getPropertyUtils().getProperty(dest, name);
                        // get current value, if its null then clone the value and set that to the value
                        if(prop == null) {
                            super.setProperty(dest, name, super.cloneBean(value));
                        } else {
                            // get the destination value and then recursively call
                            copyProperties(prop, value);
                        }
                    } catch (NoSuchMethodException e) {
                        return;
                    } catch (InstantiationException e) {
                        throw new RuntimeException("Nested property could not be cloned.", e);
                    }
                } else {
                    super.copyProperty(dest, name, value);
                }
            }
        }
    };


    for(Object source : sources) {
        recursiveBeanUtils.copyProperties(dest, source);
    }

    return dest;
}

它快速而又脏,但效果很好。因为它确实使用了递归,并且潜在的是无限递归,所以我确实放在了安全的位置。

Its kinda quick and dirty but works well. Since it does use recursion and the potential is there for infinite recursion I did place in a safety against.

这篇关于如何在java中合并两个复杂的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆