2011-07-06 41 views
10

Tôi có hai đối tượng cùng loại.Hợp nhất hai đối tượng trong 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} 

Bạn có thể vui lòng cho tôi biết cách tốt nhất để kết hợp các đối tượng này vào đối tượng đơn lẻ là gì?

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

Bạn có thể mô tả những gì bạn mong đợi single này "sáp nhập" đối tượng để trông như thế nào? – Asaph

+1

Nếu 'obj1.a =" George "' và 'obj2.a =" Lucas "' giá trị của 'obj3.a' trong đối tượng" đã hợp nhất "sẽ là gì? – Asaph

+0

Bạn có thể giả định các đối tượng là loại trừ lẫn nhau – tamilnad

Trả lời

8

Có lẽ cái gì đó như

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 có thể trả về một đối tượng mới A thay vì modifing hiện hành.

+0

Đó là những gì tôi định đề nghị - bạn phải rõ ràng mã hóa các quy tắc ở đâu đó - bạn không muốn thêm "Magic" như phản chiếu vào mã của bạn trừ khi nó hoàn toàn là khu nghỉ mát - và trường hợp này là do không có nghĩa là khó khăn. –

+3

NullPointerException vì 'this.b' có thể là' null', và nó không hoàn thành "cùng arraylist từ obj2" yêu cầu cho 'b' –

2

Nếu bạn tạo getters và setters cho thuộc tính, bạn có thể sử dụng phương thức copyProperties từ Commons BeanUtils.

2

Trong trường hợp rất đặc biệt của bạn, có vẻ như bạn muốn một đối tượng mới có các giá trị thực thực từ cả hai trường hợp. Đây là một thực hiện sẽ làm điều đó. Phương thức nên được thêm vào lớp A để có thể truy cập các trường.

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

Điều này hoạt động miễn là bạn có POJO với getters và setters riêng của họ. Phương pháp cập nhật obj với giá trị không null từ cập nhật. Nó kêu gọi setParameter() trên obj với giá trị trả về getParameter() trên cập nhật:

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

Cảm ơn câu trả lời ... Nhưng đối tượng của tôi có rất nhiều kiểu nguyên thủy như int , phao vv Nó cũng có Danh sách thành viên. – tamilnad

+0

Nevermind. Miễn là cả hai đối tượng có getXX và setXX tương ứng của nó, điều này sẽ hoạt động. Nó sẽ sao chép chỉ các giá trị với một getter và một setter –

+0

Sử dụng obj.getClass() getDeclaredMethods() để bỏ qua getClass/setClass vv và nhận các phương thức được định nghĩa trong lớp đó hoặc chỉ giao diện tương ứng. – tarkeshwar

6

Chỉ cần có sức chứa boolean đồng bộ. và phân biệt chữ hoa chữ thường (ký hiệu lạc đà)

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

Tôi đang sử dụng Spring Framework. Tôi đã phải đối mặt với cùng một vấn đề về một dự án.
Để giải quyết nó tôi sử dụng lớp BeanUtils và các phương pháp trên,

public static void copyProperties(Object source, Object target) 

Đây là một ví dụ,

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 
    } 
} 
Các vấn đề liên quan