Soru Bir listenin diğerinden öğe içerip içermediğini kontrol edin


İçlerinde farklı nesnelerle iki liste var.

List<Object1> list1;
List<Object2> list2;

Belirli bir öznitelik (Object1 ve Object2 (diğerleri arasında), bir karşılıklı öznitelik (Long türünde), attributeSame adında) bulunan list2 list1 öğesinin varlığını denetlemek istiyorum.

Şu an bunu şöyle yaparım:

boolean found = false;
for(Object1 object1 : list1){
   for(Object2 object2: list2){
       if(object1.getAttributeSame() == object2.getAttributeSame()){
           found = true;
           //also do something
       }
    }
    if(!found){
        //do something
    }
    found = false;
}

Ama bence bunu yapmanın daha iyi ve daha hızlı bir yolu var :) Biri bunu önerebilir mi?

Teşekkürler!


76
2017-08-03 13:08


Menşei


ilk olarak, bulduğunuzda = true; sonra sadece kırmak; veya döngüden çık - Shubhansh
stackoverflow.com/questions/5187888/.... Dahası, hızlı arama için İkili Arama'yı kullanmayı deneyin ve DS'nizi duruma göre değiştirin ... - Shubhansh
Object'in yanında ortak bir ebeveyn paylaşıyorlar mı? - Woot4Moo
@ Woot4Moo hayır, onlar yok - Ned


Cevaplar:


Bu, bir satırdaki giriş listelerini değiştirmeden temel JDK ile yapılabilir

!Collections.disjoint(list1, list2);

160
2017-08-03 15:59



Her ikisi de 2 farklı nesne olduğundan, bu her zaman yanlış olmaz mı? - Venki
Um, hayır mı? Nesnelerin olmaması durumunda, iki koleksiyon arasında birbirine eşittir (). - Louis Wasserman
Ayrıca, listeler için bu O (n * m) olacaktır; kopyalamak istiyorsan list1 içine Set Karşılaştırmadan önce, O (n) + O (m), yani O (n + m), ekstra bir RAM'in bedeli; hız veya hafıza arasında seçim meselesi. - Haroldo_OK
Vaov! şimdilik çalışıyor gibi görünüyor - delive
Bu cevap bir anlam ifade etmiyor. Bu, OP'nin iki nesnede tek bir spesifik değeri karşılaştırmak istediğini nasıl dikkate alır? - Zephyr


Kullanabilirsiniz Apache Commons CollectionUtils:

if(CollectionUtils.containsAny(list1,list2)) {  
    // do whatever you want
} else { 
    // do other thing 
}  

Bu, özel nesneleriniz için eşitlik işlevini düzgün şekilde aşırı yüklediğinizi varsayar.


31
2017-08-03 13:19



Ölü linç, dostum. - alexander
4 yıl oldu ve ben de açık bir şekilde paketi ve işlevi çağırıyorum. - Woot4Moo
Jdk tek çözüm olduğunda apache commons için indirim - ohcibi
@ohcibi Java da yerleşik bir logger var, sen o sırada iken Log4j ve Log4j2 kullanmayı öneren insanları inkar etmelisin. - Woot4Moo
@ Woot4Moo bağlıdır. OP4 problemini çözmek için Log4j kullanmanın bir sebebi varsa, reddetmek için bir sebep yoktur. Bu durumda apache commons, apache commons'ı öneren cevapların% 99'unda olduğu gibi, işe yaramaz bir şey değildir. - ohcibi


Var bir yöntem arasında Collection adlı retainAll ama biraz yan etkiler senin için referans

Yalnızca bu listede bulunan öğelerdeki öğeleri korur.   belirtilen koleksiyon (isteğe bağlı çalışma). Başka bir deyişle, kaldırır   bu listede yer almayan tüm öğeleri   belirtilen koleksiyon.

Bu liste arama sonucunda değiştiyse doğrudur

Gibi

boolean b = list1.retainAll(list2);

8
2017-08-03 13:23





Loius cevabı doğru, sadece bir örnek eklemek istiyorum:

listOne.add("A");
listOne.add("B");
listOne.add("C");

listTwo.add("D");
listTwo.add("E");
listTwo.add("F");      

boolean noElementsInCommon = Collections.disjoint(listOne, listTwo); // true

3
2018-02-19 16:57



İkinci liste listene 'A' öğesini eklerseniz, düşünüyorumTwoadd ("A"); Collections.disjoint olsa bile (listOne, listTwo); doğru döndürür. - Sairam Kukadala


Daha hızlı yol ilave alan gerektirecektir.

Örneğin:

  1. Tüm öğeleri bir listeye bir HashSet'e yerleştirin (object.getAttributeSame () işlevini kullanmak için karma işlevini uygulamanız gerekir)

  2. Diğer listeden geçin ve herhangi bir öğenin HashSet'te olup olmadığını kontrol edin.

Bu şekilde her nesne en çok bir kez ziyaret edilir. ve HashSet O (1) 'de herhangi bir nesneyi kontrol etmek veya eklemek için yeterince hızlıdır.


2
2017-08-03 13:20





JavaDoc'a göre .contains(Object obj):

Bu liste belirtilen öğeyi içeriyorsa true değerini döndürür. Daha   resmi olarak, yalnızca bu liste en az bir tane içeriyorsa, true değerini döndürür   öğe e öyle ki (o == null? e == null: o.equals (e)).

Bu yüzden .equals() Verilen nesne için yöntem, yapabilmeniz gerekir: if(list1.contains(object2))...

Eğer elemanlar benzersiz olacaksa (yani farklı özelliklere sahipseniz) .equals() ve .hashcode() ve her şeyi içeride sakla HashSets. Bu, sabit bir zamanda başka bir eleman içerip içermediğini kontrol etmenizi sağlayacaktır.


2
2017-08-03 13:13





daha hızlı yapmak için bir mola ekleyebilirsiniz; Bu şekilde bulunursa, döngü true olarak ayarlanır:

boolean found = false;
for(Object1 object1 : list1){
   for(Object2 object2: list2){
       if(object1.getAttributeSame() == object2.getAttributeSame()){
           found = true;
           //also do something  
           break;
       }
    }
    if(!found){
        //do something
    }
    found = false;
}

Eğer listenin yerine, attributeSame tuşları olarak haritalarınız varsa, ikinci haritada bir karşılık gelen değer varsa, bir haritadaki bir değer için daha hızlı bir şekilde kontrol edebilirsiniz.


1
2017-08-03 13:10



Merhaba Tom, fark ettiğin için teşekkürler! Evet, yazarken "kırılmayı" unuttum. Ama düşündüm de belki bir algoritma var ya da bu listeleri başka koleksiyonlara da değiştirmeliyim. - Ned
Yorumunuza cevap vermek için bir düzenleme yaptım - Tom
O (n * m) 'den daha iyi bir şey yok mu? - Woot4Moo
.getAttributeSame ()? - Manish
Object1 ve Object2'den getAttributeSame () yönteminin uygulanması sağlanmaz, aynı zamanda soru ve yanıt için de uygun değildir; Her iki sınıfın da sahip olduğu bir öznitelik (attributeSame, bir Long) döndürür. - Tom


Tuttuğunuz veri türünü tanımlayabilir misiniz? büyük veri mi? sınıflandırılmış mı? Verilere bağlı olarak farklı verimlilik yaklaşımlarını göz önünde bulundurmanız gerektiğini düşünüyorum.

Örneğin, verileriniz büyük ve listelenmemişse, iki listeyi dizinle birlikte tekrar deneyebilir ve her liste özniteliğini başka bir liste yardımcıda saklayabilirsiniz. Daha sonra yardımcı listelerdeki mevcut özniteliklere göre kontrol edebilirsiniz.

iyi şanslar

Düzenlendi: ve aşırı yükleme eşitliğini tavsiye etmem. onun tehlikeli ve muhtemelen sizin nesneye karşı anlamı anlamında.


0
2017-08-03 13:27