Bu cevapların bir numarayı kaçırdığını söyleyebilirim.
Bloch, temel, harika, özlü Etkili Java'sında , 47. maddede "Kitaplıkları tanıyın ve kullanın", "Özetlemek gerekirse, tekerleği yeniden keşfetmeyin" diyor. Ve neden olmasın birkaç çok açık neden veriyor.
Burada CollectionUtilsApache Commons Koleksiyonları kitaplığından yöntemler öneren birkaç yanıt var , ancak hiçbiri bu soruyu yanıtlamanın en güzel ve zarif yolunu bulamadı :
Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
// ... do something with the culprits, i.e. elements which are not common
}
Suçlular : yani her ikisi için ortak olmayan unsurlar Lists. Ait olan suçluların belirlenmesi list1ve hangi list2nispeten basit kullanıyor CollectionUtils.intersection( list1, culprits )ve CollectionUtils.intersection( list2, culprits ).
Bununla birlikte, {"a", "a", "b"} disjunctionile {"a", "b", "b"} gibi durumlarda dağılma eğilimindedir ... ancak bu, yazılımın bir hatası değildir, ancak istenen görevin inceliklerinin / belirsizliklerinin doğasında var.
Apache mühendisleri tarafından üretilen böyle bir görev için her zaman kaynak kodunu (l. 287) inceleyebilirsiniz . Kodlarını kullanmanın bir yararı, birçok uç durum ve öngörülebilen ve ele alınan sorunlarla baştan sona denenmiş ve test edilmiş olmasıdır. Gerekirse bu kodu kopyalayabilir ve kalbinizin içeriğine göre değiştirebilirsiniz.
NB İlk başta, CollectionUtilsyöntemlerden hiçbirinin kendi yöntemlerinizi uygulamanıza olanak tanıyan aşırı yüklenmiş bir sürüm sağlamadığı için hayal kırıklığına uğradım Comparator(böylece equalsamaçlarınıza göre yeniden tanımlayabilirsiniz ).
Ancak koleksiyonlar4 4.0'dan, Equator"T tipi nesneler arasındaki eşitliği belirleyen" yeni bir sınıf var . Collections4 CollectionUtils.java'nın kaynak kodu incelendiğinde, bunu bazı yöntemlerle kullanıyor gibi görünüyorlar, ancak anlayabildiğim kadarıyla bu, CardinalityHelpersınıfın kullanılmasıyla dosyanın üst kısmındaki yöntemler için geçerli değil ... içerir disjunctionve intersection.
Apaçilerin bunu henüz anlamadıklarını sanıyorum çünkü bu önemsiz değildir: "AbstractEquatingCollection" sınıfı gibi bir şey yaratmanız gerekirdi, bu sınıfın öğelerinin doğasında equalsve hashCodeyöntemlerini kullanmak yerine bunları kullanmak zorunda kalırsınız. ait Equatorgibi tüm temel yöntemler için add, containsvs. NB kaynak kodu baktığınızda aslında, AbstractCollectionuygulamıyor add, ne gibi onun soyut alt sınıfları yapmak AbstractSet... Eğer gibi beton sınıflarına kadar beklemek zorunda HashSetve ArrayListdaha önce adduygulanmaktadır. Oldukça baş ağrısı.
Sanırım bu arada bu alanı izleyin. Açık ara çözüm, tüm öğelerinizi, istediğiniz eşitlik türünü kullanan equalsve hashCodeuygulayan ısmarlama bir sarmalayıcı sınıfına sarmaktır ... daha sonra Collectionsbu sarmalayıcı nesnelerini manipüle etmek .