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 CollectionUtils
Apache 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 list1
ve hangi list2
nispeten basit kullanıyor CollectionUtils.intersection( list1, culprits )
ve CollectionUtils.intersection( list2, culprits )
.
Bununla birlikte, {"a", "a", "b"} disjunction
ile {"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, CollectionUtils
yö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 equals
amaç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, CardinalityHelper
sınıfın kullanılmasıyla dosyanın üst kısmındaki yöntemler için geçerli değil ... içerir disjunction
ve 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 equals
ve hashCode
yöntemlerini kullanmak yerine bunları kullanmak zorunda kalırsınız. ait Equator
gibi tüm temel yöntemler için add
, contains
vs. NB kaynak kodu baktığınızda aslında, AbstractCollection
uygulamıyor add
, ne gibi onun soyut alt sınıfları yapmak AbstractSet
... Eğer gibi beton sınıflarına kadar beklemek zorunda HashSet
ve ArrayList
daha önce add
uygulanmaktadı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 equals
ve hashCode
uygulayan ısmarlama bir sarmalayıcı sınıfına sarmaktır ... daha sonra Collections
bu sarmalayıcı nesnelerini manipüle etmek .