Java合并两个对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6591665/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 08:02:04  来源:igfitidea点击:

Merging two objects in Java

javareflection

提问by tamilnad

I have two objects of same type.

我有两个相同类型的对象。

Class A {
  String a;
  List b;
  int c;
}

A obj1 = new A();
A obj2 = new A();

obj1 => {a = "hello"; b = null; c = 10}
obj2 => {a = null; b = new ArrayList(); c = default value}

Can you please let me know what is the best way to combine this objects into single object?

您能否让我知道将这些对象组合成单个对象的最佳方法是什么?

obj3 = {a = "hello"; b = (same arraylist from obj2); c = 10}

采纳答案by Crozin

Maybe something like

也许像

class A {
    String a;
    List<..> b;
    int c;

    public void merge(A other) {
        this.a = other.a == null ? this.a : other.a;
        this.b.addAll(other.b);
        this.c = other.c == 0 ? this.c : other.c;
    }
}

A a1 = new A();
A a2 = new A();

a1.a = "a prop";
a2.c = 34;

a1.merge(a2);

A.mergemight return a new Aobject instead of modifing current.

A.merge可能会返回一个新A对象而不是修改当前对象。

回答by Thiago Duarte

If you create getters and setters for the attributes, you can use the copyPropertiesmethod from Commons BeanUtils.

如果为属性创建 getter 和 setter,则可以使用Commons BeanUtils 中的copyProperties方法。

回答by Andreas Dolk

In your very special case it looks like you want a new object that takes the realvalues from both instances. Here is an implementation that will do that. The method should be add to class Aso that it can access the fields.

在您的非常特殊的情况下,您似乎想要一个从两个实例中获取真实值的新对象。这是一个可以做到这一点的实现。该方法应该添加到类中,A以便它可以访问字段。

 public A specialMergeWith(A other) {
   A result = new A();

   result.a = (a == null ? other.a : a);
   result.b = (b == null ? other.b : b);
   result.c = (c == DEFAULT_VALUE ? other.c : c);

   return result;
 }

回答by Alex Martín Jiménez

This works as long as you have POJOs with their own getters and setters. The method updates objwith non-null values from update. It calls setParameter() on objwith the return value of getParameter() on update:

只要您拥有带有自己的 getter 和 setter 的 POJO,这就会起作用。该方法使用来自update 的非空值更新obj。它在obj上调用 setParameter() 并在update 时使用getParameter() 的返回值:

public void merge(Object obj, Object update){
    if(!obj.getClass().isAssignableFrom(update.getClass())){
        return;
    }

    Method[] methods = obj.getClass().getMethods();

    for(Method fromMethod: methods){
        if(fromMethod.getDeclaringClass().equals(obj.getClass())
                && fromMethod.getName().startsWith("get")){

            String fromName = fromMethod.getName();
            String toName = fromName.replace("get", "set");

            try {
                Method toMetod = obj.getClass().getMethod(toName, fromMethod.getReturnType());
                Object value = fromMethod.invoke(update, (Object[])null);
                if(value != null){
                    toMetod.invoke(obj, value);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
    }
}

回答by Abhay Singh

Just accommodating boolean sync. and case sensitive(camel notation)

只是适应布尔同步。并区分大小写(骆驼符号)

public boolean merge(Object obj){

    if(this.equals(obj)){
        return false;
    }

    if(!obj.getClass().isAssignableFrom(this.getClass())){
        return false;
    }

    Method[] methods = obj.getClass().getMethods();

    for(Method fromMethod: methods){
        if(fromMethod.getDeclaringClass().equals(obj.getClass())
                && (fromMethod.getName().matches("^get[A-Z].*$")||fromMethod.getName().matches("^is[A-Z].*$"))){

            String fromName = fromMethod.getName();
            String toName ;
            if(fromName.matches("^get[A-Z].*")){
                toName = fromName.replace("get", "set");
            }else{
                toName = fromName.replace("is", "set");
            }

            try {
                Method toMetod = obj.getClass().getMethod(toName, fromMethod.getReturnType());
                Object value = fromMethod.invoke(this, (Object[])null);
                if(value != null){
                    toMetod.invoke(obj, value);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
    }

    return true;
}

回答by George Siggouroglou

I am using Spring Framework. I was facing the same issue on a project.
To solve it i used the class BeanUtilsand the above method,

我正在使用 Spring 框架。我在一个项目中遇到了同样的问题。
为了解决它,我使用了类BeanUtils和上述方法,

public static void copyProperties(Object source, Object target)

This is an example,

这是一个例子,

public class Model1 {
    private String propertyA;
    private String propertyB;

    public Model1() {
        this.propertyA = "";
        this.propertyB = "";
    }

    public String getPropertyA() {
        return this.propertyA;
    }

    public void setPropertyA(String propertyA) {
        this.propertyA = propertyA;
    }

    public String getPropertyB() {
        return this.propertyB;
    }

    public void setPropertyB(String propertyB) {
        this.propertyB = propertyB;
    }
}

public class Model2 {
    private String propertyA;

    public Model2() {
        this.propertyA = "";
    }

    public String getPropertyA() {
        return this.propertyA;
    }

    public void setPropertyA(String propertyA) {
        this.propertyA = propertyA;
    }
}

public class JustATest {

    public void makeATest() {
        // Initalize one model per class.
        Model1 model1 = new Model1();
        model1.setPropertyA("1a");
        model1.setPropertyB("1b");

        Model2 model2 = new Model2();
        model2.setPropertyA("2a");

        // Merge properties using BeanUtils class.
        BeanUtils.copyProperties(model2, model1);

        // The output.
        System.out.println("Model1.propertyA:" + model1.getPropertyA(); //=> 2a
        System.out.println("Model1.propertyB:" + model1.getPropertyB(); //=> 1b
    }
}

回答by Zon

Add this method to your POJO, then use it like myObject.merge(newObject). It uses generics to loop through your POJO's fields, so you don't mention any field names:

将此方法添加到您的 POJO 中,然后像myObject.merge(newObject). 它使用泛型循环遍历 POJO 的字段,因此您无需提及任何字段名称

/**
 * Fill current object fields with new object values, ignoring new NULLs. Old values are overwritten.
 *
 * @param newObject Same type object with new values.
 */
public void merge(Object newObject) {

  assert this.getClass().getName().equals(newObject.getClass().getName());

  for (Field field : this.getClass().getDeclaredFields()) {

    for (Field newField : newObject.getClass().getDeclaredFields()) {

      if (field.getName().equals(newField.getName())) {

        try {

          field.set(
              this,
              newField.get(newObject) == null
                  ? field.get(this)
                  : newField.get(newObject));

        } catch (IllegalAccessException ignore) {
          // Field update exception on final modifier and other cases.
        }
      }
    }
  }
}

回答by Kartik Nigam

There is a dynamic solution to merge any two objects which require Reflection and Recursion.

有一个动态解决方案来合并任何两个需要反射和递归的对象。

public <T> T merge(T local, T remote, ArrayList<String> listOfClass)
        throws IllegalAccessException, InstantiationException {
    Class<?> clazz = local.getClass();
    Object merged = clazz.newInstance();
    for (Field field : clazz.getDeclaredFields()) {
        field.setAccessible(true);
        Object localValue = field.get(local);
        Object remoteValue = field.get(remote);
        if (localValue != null) {
            if (listOfClass.contains(localValue.getClass().getSimpleName())) {
                field.set(merged, this.merge(localValue, remoteValue, listOfClass));
            } else {
                field.set(merged, (remoteValue != null) ? remoteValue : localValue);
            }
        } else if (remoteValue != null) {
            field.set(merged, remoteValue);
        }
    }
    return (T) merged;
}

Variable Description:

变量说明:

  • local: The object on to which the other will be merged
  • remote: The object which will be merged to the local object
  • listOfClass: The ArrayList of custom classes in the given object
  • 本地:另一个将合并到的对象
  • 远程:将合并到本地对象的对象
  • listOfClass:给定对象中自定义类的 ArrayList

The function returns a merged object which is good to go.

该函数返回一个很好的合并对象。

Kudos! :)

荣誉!:)