2009-02-23 26 views
9

Giả sử bạn có hai trường hợp cùng loại bean và bạn muốn hiển thị tóm tắt về những gì đã thay đổi giữa hai trường hợp - ví dụ: bạn có bean đại diện cho cài đặt của người dùng trong ứng dụng của bạn và bạn ' d muốn có thể hiển thị danh sách những gì đã thay đổi trong cài đặt mới mà người dùng đang gửi (ví dụ # 1) so với những gì được lưu trữ cho người dùng (ví dụ # 2).Thuật toán phổ biến để tạo ra sự khác biệt của các trường trong hai bean?

Có một thuật toán hay mẫu thiết kế thường được sử dụng cho một tác vụ như thế này, có lẽ một cái gì đó có thể được tóm tắt và tái sử dụng cho các loại hạt khác nhau? (Tôi đang gặp khó khăn khi nghĩ đến tên tốt cho loại vấn đề này để biết Google đang làm gì). Tôi đã kiểm tra hạt đậu phộng và không có gì xuất hiện với tôi.

Trả lời

6

Nếu bạn đang nói về việc so sánh các giá trị, tôi sẽ xem xét sử dụng sự phản chiếu và chỉ so sánh chúng theo trường.

Something như thế này:


    Field[] oldFields = oldInstance.class.getDeclaredFields(); 
    Field[] newFields = newInstance.class.getDeclaredFields(); 
    StringBuilder changes = new StringBuilder(); 

    Arrays.sort(oldFields); 
    Arrays.sort(newFields); 

    int i = 0; 
    for(Field f : oldFields) 
    { 
     if(!f.equals(newFields[i])) 
     { 
      changes.append(f.getName()).append(" has changed.\n"); 
     } 
     i++; 
    } 

Mã này chưa được thử nghiệm. Bạn có thể cần phải nhận được các giá trị trong các lĩnh vực và so sánh chúng thay vì chỉ so sánh các lĩnh vực với nhau, nhưng nó sẽ làm việc trong lý thuyết.

+0

Có một số vấn đề với mã này. Đầu tiên, nó giả định rằng oldFields.length giống như newFields.length. Bạn cần một số logic để xác định các trường và trường mới bị thiếu. Cuối cùng, tôi sẽ không sử dụng vòng lặp foreach khi bạn cần tăng bộ đếm; chỉ cần sử dụng 'for'. –

+0

cả hai trường hợp của cùng một lớp học chính xác, làm cách nào để số trường của chúng khác nhau? – kgrad

+0

Ngoài ra, nếu đây là đơn luồng, bạn nên sử dụng StringBuilder thay vì StringBuffer. – cdmckay

2

Phản ánh không mantains thứ tự của Trường trong lần gọi tiếp theo: đặt hàng an toàn hơn cho mảng.

/* 
*declarations of variables 
*/ 

Arrays.sort(oldFields);//natural order - choice 1 
Arrays.sort(newFields, new Ordinator());//custom Comparator - choice 2 

/* 
*logic of comparations between elements 
*/ 

Trong lựa chọn 2 bạn có thể quyết định logic phân loại (CÁCH sắp xếp các yếu tố) với một lớp bên trong ordinator extending Comparator.

PS mã là bản nháp

3

Chúng tôi đã thực hiện điều gì đó tương tự với bean utils và nó hoạt động tốt. Những điều cần xem xét: Bạn có đi sâu vào các đối tượng trường - Nếu một người có địa chỉ và thay đổi địa chỉ, bạn có nói địa chỉ đã thay đổi hay address.postalCode đã thay đổi (chúng tôi làm) không? Bạn có trả về một danh sách tên đệm, giá trị cũ, giá trị mới từ khác biệt (chúng tôi làm) không? Làm thế nào để bạn muốn xử lý ngày - nếu tất cả những gì bạn quan tâm là phần ngày thì so sánh của bạn nên bỏ qua thời gian? Làm thế nào để bạn nói những lĩnh vực để bỏ qua?

Đây không thực sự là một câu trả lời sao chép và dán nhưng nhiều danh sách những điều không rõ ràng ngay lập tức khi chúng tôi viết khác biệt. Để thực hiện, chúng tôi chỉ có một phương pháp static util có hai bean và một danh sách các thuộc tính để so sánh và sau đó trả về một bản đồ các thuộc tính cho một Pair chứa giá trị cũ và giá trị mới. Sau đó, mỗi bean có một phương thức diff(Object o) gọi phương thức static util khi cần thiết.

+0

Tôi đang làm việc trên một yêu cầu tương tự. Giải pháp bạn vạch ra trông thú vị. Bạn có thể chia sẻ chi tiết mã hoặc thuật toán không? Cảm ơn. – krishnakumarp

+1

Tôi ước mình có thể, nhưng đó là hai công việc trước đây. Tuy nhiên, tôi đã viết một mã mẫu 'lấy cảm hứng từ' cho một cuộc phỏng vấn cách đây hai năm. Nó không làm nhiều như bản gốc, nhưng có thể hữu ích cho cảm hứng. [Tải xuống] (http://stanford.edu/~pradtke/ObjectDiffer.zip) hoặc [duyệt qua] (http://stanford.edu/~pradtke/ObjectDiffer/). – Patrick

1

Câu trả lời hay ở trên.

Nếu dữ liệu của bạn thay đổi về cấu trúc, tức là toàn bộ các trường có thể có liên quan hoặc không phụ thuộc vào các trường khác, bạn có thể muốn xem xét differential execution.

Về cơ bản, bạn có vòng lặp trên các trường và bạn tuần tự hóa các giá trị hiện tại của trường cùng một lúc khi bạn deserialize các giá trị trước, so sánh chúng như bạn đi.

Nếu có một thử nghiệm có điều kiện làm cho một khối trường có liên quan hay không, bạn tuần tự hóa/deserialize giá trị đúng hoặc sai của thử nghiệm có điều kiện và sử dụng nó để quyết định có sắp xếp hay không các trường bị ảnh hưởng. Và nó tái diễn độc đáo.

Chỉ là một đề xuất.

+0

Cảm ơn bạn đã liên kết, tôi chắc chắn sẽ xem xét điều này –

3

Những thư viện này sẽ hữu ích.

https://code.google.com/p/beandiff/ - Thư viện phân biệt bean dựa trên chú thích. Giấy phép Apache 2.0

https://github.com/SQiShER/java-object-diff/ - Một loại đậu khác nhau dựa trên mẫu Khách truy cập. Giấy phép Apache 2.0

Chúng tôi đã có yêu cầu tạo sự khác biệt giữa các hạt trong định dạng json cho mục đích kiểm tra. Chúng tôi đã thực hiện nó bằng cách sử dụng thư viện beandiff.

** CHỈNH SỬA ** Điều này trông giống như một tùy chọn mới hơn. Tôi đã không sử dụng nó mặc dù.

http://beandiff.org/

Hy vọng điều đó sẽ hữu ích.

0

Giải pháp sử dụng cấu trúc dữ liệu phản ánh và tiêu chuẩn.

Field[] declaredFields = ClassOne.class.getDeclaredFields(); 
    Field[] declaredFields2 = ClassTwo.class.getDeclaredFields(); 
    ArrayList<String> one = new ArrayList<String>(); 
    ArrayList<String> two = new ArrayList<String>(); 
    for (Field field : declaredFields) 
    { 
     one.add(field.getName()); 
    } 

    for (Field field : declaredFields2) 
    { 
     two.add(field.getName()); 
    } 

    List<String> preone = (List<String>)one.clone(); 

    one.removeAll(two); 
    two.removeAll(preone); 
    Collections.sort(one); 
    Collections.sort(two); 

    System.out.println("fields only in One : " + one); 
    System.out.println("fields only in Two : " + two); 
Các vấn đề liên quan