Java ArrayList - iki listenin eşit olup olmadığını, sıralamanın önemli olmadığını nasıl anlarım?


133

İki ArrayListtür tipim var Answer(kendi kendine yapılan sınıf).

Aynı içeriği içerip içermediklerini görmek için iki listeyi karşılaştırmak istiyorum, ancak sıralaması önemli değil.

Misal:

//These should be equal.
ArrayList<String> listA = {"a", "b", "c"}
ArrayList<String> listB = {"b", "c", "a"}

List.equalsaynı boyut, içerik ve öğe sırasına sahiplerse iki listenin eşit olduğunu belirtir. Ben de aynı şeyi istiyorum, ama düzen önemli olmadan.

Bunu yapmanın kolay bir yolu var mı? Veya iç içe geçmiş bir for döngüsü yapmam ve her iki listenin her bir dizinini manuel olarak kontrol etmem gerekecek mi?

Not: Bunları ArrayListbaşka türden bir listeye değiştiremem, öyle kalmaları gerekir.


4
bu sorunun cevabına bakın: stackoverflow.com/a/1075699/1133011
David Kroukamp

Bakın List.containsAll (liste) java
Sahil Jain

Yanıtlar:


130

Her iki listeyi de kullanarak sıralayabilir Collections.sort()ve ardından eşittir yöntemini kullanabilirsiniz. Biraz daha iyi bir çözüm, sipariş vermeden önce aynı uzunlukta olup olmadıklarını kontrol etmektir, eğer değilse, o zaman eşit değillerdir, sonra sıralayıp sonra eşittir kullanmaktır. Örneğin, iki Dize listeniz varsa, bu şöyle bir şey olacaktır:

public  boolean equalLists(List<String> one, List<String> two){     
    if (one == null && two == null){
        return true;
    }

    if((one == null && two != null) 
      || one != null && two == null
      || one.size() != two.size()){
        return false;
    }

    //to avoid messing the order of the lists we will use a copy
    //as noted in comments by A. R. S.
    one = new ArrayList<String>(one); 
    two = new ArrayList<String>(two);   

    Collections.sort(one);
    Collections.sort(two);      
    return one.equals(two);
}

20
Orijinal listenin sırasını bozmamayı unutmayın (olduğu Collections.sortgibi) - yani bir kopyasını iletin.
arshajii

@ARS evet, bu kesin bir yan etkidir, ancak yalnızca kendi durumunda önemliyse.
Jacob Schoen

3
one = new ArrayList<String>(one); two = new ArrayList<String>(two);Argümanları mahvetmekten kaçınmak için sadece ekleyebilirsiniz .
arshajii

@jschoen Collections.sort () yapmaya çalışmak bana şu hatayı veriyor: Bağlı uyumsuzluk: Collections türünün genel yöntem sıralaması (List <T>) argümanlar (ArrayList <Answer>) için geçerli değil. Yanıt türü, sınırlı <T extends Comparable <? Parametresinin geçerli bir ikamesi değildir. super T >>
iaacp

3
İşlevin içindeki ikinci "eğer" ifadesi if(one == null || two == null || one.size() != two.size()){ return false; }, hem bir hem de
Hugo

151

Muhtemelen herhangi bir liste için en kolay yol şudur :

listA.containsAll(listB) && listB.containsAll(listA)

5
Bunun eğlencesi nerede? Tüm ciddiyetle, bu muhtemelen daha iyi bir çözümdür.
Jacob Schoen

67
Bağlıdır [a, b, c]ve [c, b, a, b]aynı içeriğe sahip olduğu kabul edilir. Bu cevap yaptıklarını söylerdi, ancak OP için yapmadıkları olabilir (çünkü biri bir kopya içerirken diğeri içermiyor). Verimlilik sorunları hakkında hiçbir şey söylememek.
yshavit

4
yorumlara göre iyileştirme - System.out.println (((l1.size () == l2.size ()) && l2.containsAll (l1) && l1.containsAll (l2)));
Nrj

8
@Nrj, peki ya [1,2,2] ve [2,1,1]?
ROMANIA_engineer

3
Bu yaklaşımın karmaşıklığı O (n ^ 2). Ters sırada iki liste düşünün, örneğin: [1,2,3] ve [3,2,1]. İlk öğe için n öğeyi, ikinci n-1 öğeleri vb. Taraması gerekecektir. Dolayısıyla karmaşıklık n ^ 2 mertebesinde olacaktır. Bence daha iyi bir yol sıralayıp sonra eşitleri kullanmak olacak. O O (n * log (n)) karmaşıklığını olacak
puneet

90

Apache Commons Koleksiyonları bir kez daha kurtarmaya:

List<String> listA = Arrays.asList("a", "b", "b", "c");
List<String> listB = Arrays.asList("b", "c", "a", "b");
System.out.println(CollectionUtils.isEqualCollection(listA, listB)); // true

 

List<String> listC = Arrays.asList("a", "b", "c");
List<String> listD = Arrays.asList("a", "b", "c", "c");
System.out.println(CollectionUtils.isEqualCollection(listC, listD)); // false

Dokümanlar:

org.apache.commons.collections4.CollectionUtils

public static boolean isEqualCollection(java.util.Collection a,
                                        java.util.Collection b)

İade trueverilen IFF Collections tam olarak aynı kardinallikleri ile tam olarak aynı öğeler içerir.

Kendisine, kardinalitesi IFF e içinde bir kardinalitesi eşittir e de b her bir eleman için, e içinde bir ya da b .

Parametreler:

  • a - ilk koleksiyon olmamalıdır null
  • b - ikinci koleksiyon, olmamalıdır null

İade: trueKoleksiyonlar aynı temel özelliklere sahip aynı öğeleri içeriyorsa.


Uygulama, DiddiZ'in cevabına aşağı yukarı benzer görünüyor.
user227353

Tamam ... peki ya suçluları ele geçirmeye ne dersiniz (iki listede ortak olmayan unsurlar) cevap ise false? Cevabımı gör.
mike rodent

implementation 'org.apache.commons:commons-collections4:4.3'bana bir hata Caused by: com.android.builder.dexing.DexArchiveBuilderException: Failed to process yolu bıraktı .
Aliton Oliveira

13
// helper class, so we don't have to do a whole lot of autoboxing
private static class Count {
    public int count = 0;
}

public boolean haveSameElements(final List<String> list1, final List<String> list2) {
    // (list1, list1) is always true
    if (list1 == list2) return true;

    // If either list is null, or the lengths are not equal, they can't possibly match 
    if (list1 == null || list2 == null || list1.size() != list2.size())
        return false;

    // (switch the two checks above if (null, null) should return false)

    Map<String, Count> counts = new HashMap<>();

    // Count the items in list1
    for (String item : list1) {
        if (!counts.containsKey(item)) counts.put(item, new Count());
        counts.get(item).count += 1;
    }

    // Subtract the count of items in list2
    for (String item : list2) {
        // If the map doesn't contain the item here, then this item wasn't in list1
        if (!counts.containsKey(item)) return false;
        counts.get(item).count -= 1;
    }

    // If any count is nonzero at this point, then the two lists don't match
    for (Map.Entry<String, Count> entry : counts.entrySet()) {
        if (entry.getValue().count != 0) return false;
    }

    return true;
}

Vay canına, bunun diğer tüm çözümlerden daha hızlı performans gösterdiğini görünce gerçekten şaşırdım. Ve erken çıkışı destekler.
DiddiZ

Bu aynı zamanda ikinci döngüde kısa devre yapabilir, eğer countnegatif olursa , döngü gövdesini basitleştirebilir. if(!counts.containsKey(item) || --counts.get(item).count < 0) return false;Ayrıca, 3. döngü basitleştirilebilirfor(Count c: counts.values()) if(c.count != 0) return false;
Holger

@Holger Birincisine benzer bir şey düşünmüştüm (sıfıra ulaştığında sayıyı kaldırmak, aynı etkiye sahip olacak, ancak aynı zamanda kontrolleri " countsboş olup olmadığını geri döndür" e çevirecek ), ancak gizlemek istemedim ana nokta: bir harita kullanmanın temelde bunu bir O (N + M) problemine dönüştürmesi ve muhtemelen elde edeceğiniz en büyük destek.
cHao

@cHao evet, öncekilerden daha iyi bir zaman karmaşıklığına sahip bir çözüme işaret ettiğiniz için krediyi hak ediyorsunuz. Aklıma geldi, çünkü yinelemelerle ilgili yakın zamanda benzer bir soru var. Artık Java 8'e sahip olduğumuz için, onu yeniden düşünmeye değerdi. Sayı negatif olduğunda ikinci döngüde kısa devre yaparsanız, üçüncü döngü kullanılmaz hale gelir. Ayrıca, bokstan kaçınmak iki ucu keskin bir kılıç olabilir; yeni Map.merge, kutulu tamsayılar kullanmak çoğu kullanım durumu için daha basit ve daha verimli olabilir. Bu yanıta da bakın …
Holger

10

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 .


Ayrıca bilge biri "Bağımlılığın maliyetini bilin" dedi
Stanislaw Baranski

@StanislawBaranski Bu ilginç bir yorum. Bu tür kitaplıklara çok fazla bağımlı olunmaması gerektiği bir öneri mi? Bir bilgisayarda bir işletim sistemi kullandığınızda, bu zaten büyük bir inanç sıçraması değil mi? Apache kitaplıklarını kullanmaktan mutlu olmamın nedeni, onları gerçekten çok yüksek kalitede kabul etmem ve yöntemlerinin "sözleşmelerine" uygun olduğunu ve kapsamlı bir şekilde test edildiğini varsaymam. Daha çok güvendiğiniz kendi kodunuzu geliştirmek ne kadar zaman alırsınız? Kodu açık kaynak Apache kitaplıklarından kopyalamak ve incelemek düşünülmesi gereken bir şey olabilir ...
mike rodent

8

Öğelerin önemi önemli değilse (anlamı: tekrarlanan öğeler tek olarak kabul edilir), bunu sıralamak zorunda kalmadan yapmanın bir yolu vardır:

boolean result = new HashSet<>(listA).equals(new HashSet<>(listB));

Bu yaratacak Sether out Listve kullanılacak HashSet'in equalsyöntemi göz ardı eder (ders) sipariş.

Kardinalite önemliyse, kendinizi şu kurumun sağladığı imkanlarla sınırlamalısınız List; @ jschoen'in cevabı bu durumda daha uygun olacaktır.


ya listA = [a, b, c, c] ve listB = [a, b, c] ise. sonuç doğru olacaktır, ancak listeler eşit değildir.
Nikolas

6

Listeleri Guava'nın Multiset'ine dönüştürmek çok iyi çalışıyor. Sıralarına bakılmaksızın karşılaştırılırlar ve yinelenen unsurlar da dikkate alınır.

static <T> boolean equalsIgnoreOrder(List<T> a, List<T> b) {
    return ImmutableMultiset.copyOf(a).equals(ImmutableMultiset.copyOf(b));
}

assert equalsIgnoreOrder(ImmutableList.of(3, 1, 2), ImmutableList.of(2, 1, 3));
assert !equalsIgnoreOrder(ImmutableList.of(1), ImmutableList.of(1, 1));

6

Bu, @ cHao çözümüne dayanmaktadır. Birkaç düzeltme ve performans iyileştirmesi ekledim. Bu, eşit sıralı kopyalama çözümünün kabaca iki katı kadar hızlı çalışır. Herhangi bir koleksiyon türü için çalışır. Boş koleksiyonlar ve null eşit kabul edilir. Avantajınız için kullanın;)

/**
 * Returns if both {@link Collection Collections} contains the same elements, in the same quantities, regardless of order and collection type.
 * <p>
 * Empty collections and {@code null} are regarded as equal.
 */
public static <T> boolean haveSameElements(Collection<T> col1, Collection<T> col2) {
    if (col1 == col2)
        return true;

    // If either list is null, return whether the other is empty
    if (col1 == null)
        return col2.isEmpty();
    if (col2 == null)
        return col1.isEmpty();

    // If lengths are not equal, they can't possibly match
    if (col1.size() != col2.size())
        return false;

    // Helper class, so we don't have to do a whole lot of autoboxing
    class Count
    {
        // Initialize as 1, as we would increment it anyway
        public int count = 1;
    }

    final Map<T, Count> counts = new HashMap<>();

    // Count the items in col1
    for (final T item : col1) {
        final Count count = counts.get(item);
        if (count != null)
            count.count++;
        else
            // If the map doesn't contain the item, put a new count
            counts.put(item, new Count());
    }

    // Subtract the count of items in col2
    for (final T item : col2) {
        final Count count = counts.get(item);
        // If the map doesn't contain the item, or the count is already reduced to 0, the lists are unequal 
        if (count == null || count.count == 0)
            return false;
        count.count--;
    }

    // At this point, both collections are equal.
    // Both have the same length, and for any counter to be unequal to zero, there would have to be an element in col2 which is not in col1, but this is checked in the second loop, as @holger pointed out.
    return true;
}

Bir toplam sayacı kullanarak son for-döngüsünü atlayabilirsiniz. Toplam sayacı, her aşamadaki toplam sayımı sayacaktır. İlk döngüde toplam sayacını artırın ve ikinci döngüde azaltın. Toplam sayacı 0'dan büyükse listeler eşleşmez, aksi halde eşleşirler. Şu anda, son döngüde tüm sayımların sıfır olup olmadığını veya başka bir deyişle, tüm sayıların toplamının sıfır olup olmadığını kontrol edersiniz. Toplam sayacı türünü kullanmak, bu denetimi tersine çevirir, sayıların toplamı sıfırsa doğru, aksi takdirde yanlış döndürür.
Cts

IMO, bu for-döngüsünü atlamaya değer çünkü listeler eşleştiğinde (en kötü durum senaryosu) for-döngüsü başka bir gereksiz O (n) ekler.
Cts

@SatA aslında herhangi bir değişiklik yapmadan 3. döngüyü kaldırabilirsiniz. İkinci döngü, falsebir anahtar olmadığında veya sayısı negatif olduğunda zaten geri döner . Her iki listenin toplam boyutu eşleştiğinden (bu önceden kontrol edilmiştir), başka bir anahtar için negatif değerler olmayan bir anahtar için pozitif değerler olamayacağından, ikinci döngüden sonra sıfır olmayan değerlere sahip olmak imkansızdır.
Holger

@holger kesinlikle haklısın. Anladığım kadarıyla 3. döngü hiç gerekli değil.
Cts

@SatA… ve Java 8 ile bu, bu cevapta olduğu gibi kısaca uygulanabilir .
Holger

5

Bilgisayar veya programlama dili olmadan bunu kendiniz nasıl yapacağınızı düşünün. Size iki öğe listesi veriyorum ve aynı öğeleri içerip içermediklerini bana söylemelisiniz. Nasıl yapardın?

Yukarıda bahsedildiği gibi bir yaklaşım, listeleri sıralamak ve ardından eşit olup olmadıklarını görmek için öğe öğe gitmektir (ne List.equalsyapar). Bu, listeleri değiştirmenize veya kopyalamanıza izin verildiği anlamına gelir - ve atamayı bilmeden, bunlardan birine / ikisine de izin verilip verilmediğini bilemiyorum.

Başka bir yaklaşım, her bir listeyi gözden geçirerek, her bir öğenin kaç kez göründüğünü saymaktır. Her iki listenin sonunda aynı sayılar varsa, aynı öğeleri içerirler. Bunun kodu, her listeyi bir haritaya çevirmek elem -> (# of times the elem appears in the list)ve ardından equalsiki haritayı çağırmak olacaktır. Haritalar öyleyse HashMap, bu çevirilerin her biri, karşılaştırma gibi bir O (N) işlemidir. Bu, fazladan bellek pahasına size zaman açısından oldukça verimli bir algoritma verecek.


5

Aynı sorunu yaşadım ve farklı bir çözüm buldum. Bu, kopyalar söz konusu olduğunda da işe yarar:

public static boolean equalsWithoutOrder(List<?> fst, List<?> snd){
  if(fst != null && snd != null){
    if(fst.size() == snd.size()){
      // create copied lists so the original list is not modified
      List<?> cfst = new ArrayList<Object>(fst);
      List<?> csnd = new ArrayList<Object>(snd);

      Iterator<?> ifst = cfst.iterator();
      boolean foundEqualObject;
      while( ifst.hasNext() ){
        Iterator<?> isnd = csnd.iterator();
        foundEqualObject = false;
        while( isnd.hasNext() ){
          if( ifst.next().equals(isnd.next()) ){
            ifst.remove();
            isnd.remove();
            foundEqualObject = true;
            break;
          }
        }

        if( !foundEqualObject ){
          // fail early
          break;
        }
      }
      if(cfst.isEmpty()){ //both temporary lists have the same size
        return true;
      }
    }
  }else if( fst == null && snd == null ){
    return true;
  }
  return false;
}

Diğer bazı çözümlere kıyasla avantajlar:

  • O (N²) karmaşıklığından daha az (buradaki diğer yanıtlardaki çözümlerle karşılaştırıldığında gerçek performansını test etmemiş olsam da);
  • erken çıkar;
  • null için kontroller;
  • yinelenenler dahil olduğunda bile çalışır: bir diziniz [1,2,3,3]ve başka bir diziniz varsa, [1,2,2,3]buradaki çoğu çözüm, sırayı dikkate almadığınızda size aynı olduklarını söyler. Bu çözüm, geçici listelerden eşit öğeleri kaldırarak bunu önler;
  • anlamsal eşitlik ( equals) kullanır ve eşitlik referansını kullanmaz ( ==);
  • değil, bu yüzden implement Comparablebu çözümün çalışması için sıralanabilir (göre ) olmaları gerekmez .

3

Koleksiyonları sıralamayı ummuyorsanız ve ["A" "B" "C"] 'nin ["B" "B" "A" "C"]' ye eşit olmadığı sonucuna ihtiyacınız varsa,

l1.containsAll(l2)&&l2.containsAll(l1)

yeterli değil, muhtemelen boyutu da kontrol etmeniz gerekiyor:

    List<String> l1 =Arrays.asList("A","A","B","C");
    List<String> l2 =Arrays.asList("A","B","C");
    List<String> l3 =Arrays.asList("A","B","C");

    System.out.println(l1.containsAll(l2)&&l2.containsAll(l1));//cautions, this will be true
    System.out.println(isListEqualsWithoutOrder(l1,l2));//false as expected

    System.out.println(l3.containsAll(l2)&&l2.containsAll(l3));//true as expected
    System.out.println(isListEqualsWithoutOrder(l2,l3));//true as expected


    public static boolean isListEqualsWithoutOrder(List<String> l1, List<String> l2) {
        return l1.size()==l2.size() && l1.containsAll(l2)&&l2.containsAll(l1);
}

2

CollectionUtils çıkarma yöntemini kullanan çözüm:

import static org.apache.commons.collections15.CollectionUtils.subtract;

public class CollectionUtils {
  static public <T> boolean equals(Collection<? extends T> a, Collection<? extends T> b) {
    if (a == null && b == null)
      return true;
    if (a == null || b == null || a.size() != b.size())
      return false;
    return subtract(a, b).size() == 0 && subtract(a, b).size() == 0;
  }
}

1

Sırayı önemsiyorsanız, eşittir yöntemini kullanın:

list1.equals(list2)

Siparişi önemsemiyorsanız, bunu kullanın

Collections.sort(list1);
Collections.sort(list2);      
list1.equals(list2)

4
O diyor gelmez sırayla önemsiyorum.
mike rodent

0

Her iki dünyanın da en iyisi [@DiddiZ, @Chalkos]: Bu, esas olarak @Chalkos yöntemine dayanır, ancak bir hatayı düzeltir (ifst.next ()) ve ilk kontrolleri (@DiddiZ'den alınan) iyileştirir ve ayrıca ilk koleksiyonu kopyala (yalnızca öğeleri ikinci koleksiyonun bir kopyasından kaldırır).

Bir karma işlevi veya sıralama gerektirmeyen ve eşitlikten uzak bir erken varolmayı mümkün kılan bu, şimdiye kadarki en verimli uygulama. Binlerce veya daha fazla koleksiyon uzunluğuna ve çok basit bir hash işlevine sahip değilseniz.

public static <T> boolean isCollectionMatch(Collection<T> one, Collection<T> two) {
    if (one == two)
        return true;

    // If either list is null, return whether the other is empty
    if (one == null)
        return two.isEmpty();
    if (two == null)
        return one.isEmpty();

    // If lengths are not equal, they can't possibly match
    if (one.size() != two.size())
        return false;

    // copy the second list, so it can be modified
    final List<T> ctwo = new ArrayList<>(two);

    for (T itm : one) {
        Iterator<T> it = ctwo.iterator();
        boolean gotEq = false;
        while (it.hasNext()) {
            if (itm.equals(it.next())) {
                it.remove();
                gotEq = true;
                break;
            }
        }
        if (!gotEq) return false;
    }
    // All elements in one were found in two, and they're the same size.
    return true;
}

Yanılmıyorsam, bu algoritmanın bir değer durum senaryosundaki karmaşıklığı (listelerin eşit olduğu ancak ters bir şekilde sıralandığı) O (N * N!) Olacaktır.
Cts

Aslında, O (N * (N / 2)) olur, her yinelemede olduğu gibi, dizi boyutu azalır.
jazzgil

0

Boş değerler içerebilen dizi listelerinin eşitliğini kontrol etmenin alternatif bir yoludur:

List listA = Arrays.asList(null, "b", "c");
List listB = Arrays.asList("b", "c", null);

System.out.println(checkEquality(listA, listB)); // will return TRUE


private List<String> getSortedArrayList(List<String> arrayList)
{
    String[] array = arrayList.toArray(new String[arrayList.size()]);

    Arrays.sort(array, new Comparator<String>()
    {
        @Override
        public int compare(String o1, String o2)
        {
            if (o1 == null && o2 == null)
            {
                return 0;
            }
            if (o1 == null)
            {
                return 1;
            }
            if (o2 == null)
            {
                return -1;
            }
            return o1.compareTo(o2);
        }
    });

    return new ArrayList(Arrays.asList(array));
}

private Boolean checkEquality(List<String> listA, List<String> listB)
{
    listA = getSortedArrayList(listA);
    listB = getSortedArrayList(listB);

    String[] arrayA = listA.toArray(new String[listA.size()]);
    String[] arrayB = listB.toArray(new String[listB.size()]);

    return Arrays.deepEquals(arrayA, arrayB);
}

Listeler ve diziler arasındaki tüm bu kopyalamanın ne anlamı var?
Holger

0

Bunun için benim çözümüm. Çok havalı değil ama iyi çalışıyor.

public static boolean isEqualCollection(List<?> a, List<?> b) {

    if (a == null || b == null) {
        throw new NullPointerException("The list a and b must be not null.");
    }

    if (a.size() != b.size()) {
        return false;
    }

    List<?> bCopy = new ArrayList<Object>(b);

    for (int i = 0; i < a.size(); i++) {

        for (int j = 0; j < bCopy.size(); j++) {
            if (a.get(i).equals(bCopy.get(j))) {
                bCopy.remove(j);
                break;
            }
        }
    }

    return bCopy.isEmpty();
}

-1

Bu durumda, {"a", "b"} ve {"b", "a"} listeleri eşittir. Ve {"a", "b"} ve {"b", "a", "c"} eşit değildir. Karmaşık nesnelerin listesini kullanırsanız , containsAll içinde kullandığı için eşittir yöntemini geçersiz kılmayı unutmayın .

if (oneList.size() == secondList.size() && oneList.containsAll(secondList)){
        areEqual = true;
}

-1: {"a", "a", "b"} ve {"a", "b", "b"} ile yanlış cevap verir: kaynak kodunu kontrol edin AbstractCollection.containsAll(). Hakkında Listsdeğil , bahsettiğimiz gibi yinelenen öğelere izin vermelisiniz Sets. Lütfen cevabıma bakın.
mike rodent
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.