Tôi muốn nói những câu trả lời này bỏ lỡ một mẹo.
Bloch, trong Java hiệu quả , thiết yếu, tuyệt vời, ngắn gọn của mình , nói, trong mục 47, tiêu đề "Biết và sử dụng các thư viện", "Để tóm tắt, đừng phát minh lại bánh xe". Và ông đưa ra một số lý do rất rõ ràng tại sao không.
Có một vài câu trả lời ở đây gợi ý các phương thức CollectionUtils
trong thư viện Bộ sưu tập Apache Commons nhưng không có câu trả lời nào phát hiện ra cách trả lời đẹp nhất, thanh lịch nhất cho câu hỏi này :
Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
// ... do something with the culprits, i.e. elements which are not common
}
Thủ phạm : tức là các yếu tố không phổ biến cho cả hai Lists
. Xác định thủ phạm thuộc về ai list1
và list2
tương đối đơn giản bằng cách sử dụng CollectionUtils.intersection( list1, culprits )
vàCollectionUtils.intersection( list2, culprits )
.
Tuy nhiên, nó có xu hướng sụp đổ trong các trường hợp như {"a", "a", "b"} disjunction
với {"a", "b", "b"} ... ngoại trừ điều này không phải là lỗi của phần mềm, nhưng vốn có bản chất của sự tinh tế / mơ hồ của nhiệm vụ mong muốn.
Bạn luôn có thể kiểm tra mã nguồn (l. 287) cho một nhiệm vụ như thế này, do các kỹ sư Apache sản xuất. Một lợi ích của việc sử dụng mã của họ là nó sẽ được thử nghiệm và kiểm tra kỹ lưỡng, với nhiều trường hợp cạnh và các vấn đề được dự đoán và xử lý. Bạn có thể sao chép và điều chỉnh mã này vào nội dung trái tim của bạn nếu cần.
NB Lúc đầu tôi thất vọng vì không có CollectionUtils
phương pháp nào cung cấp phiên bản quá tải cho phép bạn áp đặt chính mình Comparator
(vì vậy bạn có thể xác định lạiequals
cho phù hợp với mục đích của mình).
Nhưng từ bộ sưu tập4 4.0, có một lớp mới, Equator
"xác định sự bình đẳng giữa các đối tượng loại T". Khi kiểm tra mã nguồn của bộ sưu tập4 CollectionUtils.java dường như họ đang sử dụng phương thức này với một số phương thức, nhưng theo như tôi có thể thấy thì điều này không thể áp dụng cho các phương thức ở đầu tệp, sử dụng CardinalityHelper
lớp ... bao gồm disjunction
và intersection
.
Tôi đoán rằng người Apache chưa hiểu về điều này bởi vì nó không tầm thường: bạn sẽ phải tạo ra một thứ như lớp "AbstractEquatingCollection", thay vì sử dụng các phần tử vốn có của nó equals
và hashCode
các phương thức thay vào đó sẽ phải sử dụng các phương thức đó của Equator
cho tất cả các phương pháp cơ bản, chẳng hạn như add
, contains
vv NB trên thực tế khi bạn nhìn vào mã nguồn, AbstractCollection
không thực hiện add
, cũng không phân lớp trừu tượng của nó như AbstractSet
... bạn phải đợi cho đến khi lớp bê tông như HashSet
và ArrayList
trước add
được thực thi. Khá đau đầu.
Trong thời gian đó xem không gian này, tôi cho rằng. Giải pháp tạm thời rõ ràng sẽ là bọc tất cả các thành phần của bạn trong một lớp bao bọc bespoke sử dụng equals
và hashCode
thực hiện loại đẳng thức bạn muốn ... sau đó thao tác Collections
với các đối tượng trình bao bọc này.