2011-07-06 4 views
10

J'ai deux objets de même type.Fusion de deux objets en Java

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} 

Pouvez-vous s'il vous plaît laissez-moi savoir quelle est la meilleure façon de combiner ces objets en objet unique?

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

Pouvez-vous décrire ce que vous attendez ce seul objet « fusionné » pour ressembler? – Asaph

+1

Si 'obj1.a =" George "' et 'obj2.a =" Lucas "' quelle devrait être la valeur de 'obj3.a' dans l'objet" fusionné "? – Asaph

+0

Vous pouvez supposer que les objets sont mutuellement exclusifs – tamilnad

Répondre

8

Peut-être quelque chose comme

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.merge pourrait retourner un nouvel objet A au lieu de modifing courant.

+0

C'est ce que j'allais recommander - vous devez coder clairement les règles quelque part - vous ne voulez pas ajouter "Magic" comme réflexion à votre code sauf si c'est absolument le dernier resort - et ce cas n'est en aucun cas si difficile. –

+3

NullPointerException depuis 'this.b' pourrait être' null', et il ne remplit pas la demande "même arraylist from obj2" pour 'b' –

2

Si vous créez des accesseurs pour les attributs, vous pouvez utiliser la méthode copyProperties de la Chambre des communes BeanUtils.

2

Dans votre cas très particulier, il semble que vous vouliez un nouvel objet qui prenne les valeurs réelles des deux instances. Voici une implémentation qui va le faire. La méthode doit être ajoutée à la classe A afin qu'elle puisse accéder aux champs.

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; 
} 
21

Cela fonctionne aussi longtemps que vous avez POJO avec leurs propres accesseurs. La méthode met à jour obj avec des valeurs non nulles de mise à jour. Il appelle setParameter() sur obj avec la valeur de retour de getParameter() sur mise à jour:

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(); 
      } 
     } 
    } 
} 
+0

Merci pour la réponse ... Mais mon objet a beaucoup de types primitifs comme int , float etc Il a également List en tant que membres. – tamilnad

+0

Peu importe. Tant que les deux objets ont getXX et son setXX correspondant, cela fonctionnera. Copie juste les valeurs avec un getter ET un setter –

+0

Utilisez obj.getClass(). GetDeclaredMethods() pour ignorer getClass/setClass etc et obtenir les méthodes définies dans cette classe ou l'interface correspondante uniquement. – tarkeshwar

6

Juste accueillir la synchronisation booléenne. et sensible à la casse (notation camel)

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; 
} 
5

J'utilise Spring Framework. Je faisais face au même problème sur un projet.
Pour le résoudre i utilisé la classe BeanUtils et la méthode ci-dessus,

public static void copyProperties(Object source, Object target) 

Ceci est un exemple,

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 
    } 
}