Java ArrayList - bagaimana saya bisa tahu jika dua daftar sama, agar tidak menjadi masalah?

133

Saya memiliki dua ArrayListtipe Answer(kelas buatan sendiri).

Saya ingin membandingkan dua daftar untuk melihat apakah mereka berisi konten yang sama, tetapi tanpa masalah urutan.

Contoh:

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

List.equalsmenyatakan bahwa dua daftar sama jika mengandung ukuran, isi, dan urutan elemen yang sama. Saya menginginkan hal yang sama, tetapi tanpa ketertiban.

Apakah ada cara sederhana untuk melakukan hal ini? Atau apakah saya perlu melakukan nested for loop, dan secara manual memeriksa setiap indeks dari kedua daftar?

Catatan: Saya tidak bisa mengubahnya dari ArrayListjenis daftar lain, mereka harus tetap seperti itu.

iaacp
sumber
4
lihat jawaban untuk pertanyaan ini: stackoverflow.com/a/1075699/1133011
David Kroukamp
Lihat List.containsAll (daftar) di java
Sahil Jain

Jawaban:

130

Anda bisa mengurutkan kedua daftar menggunakan Collections.sort()dan kemudian menggunakan metode equals. Solusi yang sedikit lebih baik adalah dengan pertama memeriksa apakah mereka memiliki panjang yang sama sebelum memesan, jika mereka tidak, maka mereka tidak sama, lalu mengurutkan, lalu gunakan sama. Misalnya, jika Anda memiliki dua daftar Strings, itu akan menjadi seperti:

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);
}
Jacob Schoen
sumber
20
Ingatlah untuk tidak menghancurkan urutan daftar asli (seperti Collections.sorthalnya) - yaitu meneruskan salinan.
arshajii
@ ARS ya itu adalah efek samping yang pasti, tetapi hanya jika itu penting dalam kasus khusus mereka.
Jacob Schoen
3
Anda bisa menambahkan one = new ArrayList<String>(one); two = new ArrayList<String>(two);untuk menghindari merusak argumen.
arshajii
@jschoen Mencoba melakukan Collections.sort () memberi saya kesalahan ini: Ketidakcocokan batas: Jenis metode generik (Daftar <T>) dari tipe Koleksi tidak berlaku untuk argumen (ArrayList <Answer>). Jenis jawaban yang disimpulkan bukan pengganti yang valid untuk parameter terikat <T extends Comparable <? super T >>
iaacp
3
Pernyataan kedua "jika" fungsi di dalam dapat disederhanakan if(one == null || two == null || one.size() != two.size()){ return false; }karena Anda sudah memeriksa apakah satu dan dua adalah null
Hugo
151

Mungkin cara termudah untuk daftar mana pun adalah:

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

sumber
5
Di mana kesenangannya? Meskipun serius ini mungkin solusi yang lebih baik.
Jacob Schoen
67
Tergantung pada apakah [a, b, c]dan [c, b, a, b]dianggap memiliki konten yang sama. Jawaban ini akan mengatakan bahwa mereka melakukannya, tetapi bisa jadi untuk OP mereka tidak (karena satu berisi duplikat dan yang lainnya tidak). Untuk tidak mengatakan masalah efisiensi.
yshavit
4
penyempurnaan berdasarkan komentar - System.out.println (((l1.size () == l2.size ()) && l2.containsAll (l1) && l1.containsAll (l2)));
Nrj
8
@Nrj, bagaimana dengan [1,2,2] dan [2,1,1]?
ROMANIA_engineer
3
Pendekatan ini memiliki kompleksitas O (n ^ 2). Pertimbangkan dua daftar yang berada dalam urutan terbalik, misalnya: [1,2,3] dan [3,2,1]. Untuk elemen pertama harus memindai elemen n, untuk elemen n-1 kedua dan seterusnya. Jadi kompleksitas akan menjadi urutan n ^ 2. Saya pikir cara yang lebih baik adalah menyortir dan kemudian menggunakan equals. Ini akan memiliki kompleksitas O (n * log (n))
puneet
90

Apache Commons Collections untuk menyelamatkan sekali lagi:

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

Docs:

org.apache.commons.collections4.CollectionUtils

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

Mengembalikan trueiff yang diberikan Collectionmengandung elemen yang persis sama dengan kardinalitas yang persis sama.

Yaitu, jika kardinalitas e dalam a sama dengan kardinalitas e dalam b , untuk setiap elemen e dalam a atau b .

Parameter:

  • a - koleksi pertama, tidak boleh null
  • b - koleksi kedua, tidak boleh null

Pengembalian: truejika koleksi mengandung elemen yang sama dengan kardinalitas yang sama.

acdcjunior
sumber
Implementasinya sepertinya kurang lebih sama dengan jawaban DiddiZ.
user227353
OKE ... tapi bagaimana dengan menghubungi pelakunya (elemen yang tidak umum untuk dua daftar) jika jawabannya false? Lihat jawaban saya.
mike rodent
implementation 'org.apache.commons:commons-collections4:4.3'telah meninggalkan saya dengan Caused by: com.android.builder.dexing.DexArchiveBuilderException: Failed to process jalur kesalahan .
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;
}
cao
sumber
Wow, sangat terkejut menemukan ini melakukan lebih cepat daripada semua solusi lainnya. Dan itu mendukung sejak awal.
DiddiZ
Ini juga dapat menyebabkan hubungan pendek di loop kedua, jika countmenjadi negatif, menyederhanakan tubuh loop ke if(!counts.containsKey(item) || --counts.get(item).count < 0) return false;Juga, loop ke-3 dapat disederhanakan menjadifor(Count c: counts.values()) if(c.count != 0) return false;
Holger
@ Holger Saya telah mempertimbangkan sesuatu yang mirip dengan yang pertama (menghapus hitungan ketika mencapai nol, yang akan memiliki efek yang sama tetapi juga mengubah cek di akhir menjadi "mengembalikan apakah countskosong"), tetapi tidak ingin mengaburkan poin utama: bahwa menggunakan peta pada dasarnya mengubah ini menjadi masalah O (N + M), dan merupakan dorongan tunggal terbesar yang mungkin Anda dapatkan.
cao
@ cHao ya, Anda layak mendapatkan kredit karena menunjukkan solusi dengan kompleksitas waktu yang lebih baik daripada yang sebelumnya. Saya kebetulan memikirkannya, karena ada pertanyaan serupa tentang iterables baru-baru ini. Karena kita juga sekarang memiliki Java 8, layak untuk dipikirkan kembali. Jika Anda mengalami hubungan pendek di loop kedua ketika nomor menjadi negatif, loop ketiga menjadi usang. Lebih jauh, menghindari tinju mungkin merupakan pedang bermata dua, dengan Map.mergebilangan bulat kotak baru mungkin lebih sederhana dan lebih efisien untuk sebagian besar kasus penggunaan. Lihat juga jawaban ini ...
Holger
10

Saya akan mengatakan jawaban ini melewatkan tipuan.

Bloch, dalam Java Efektifnya yang esensial, luar biasa, dan ringkas , mengatakan, dalam item 47, judul "Ketahui dan gunakan perpustakaan", "Untuk meringkas, jangan menemukan kembali roda". Dan dia memberikan beberapa alasan yang sangat jelas mengapa tidak.

Ada beberapa jawaban di sini yang menyarankan metode-metode dari CollectionUtilsdalam pustaka Apache Commons Collections tetapi tidak ada yang menemukan cara paling indah dan elegan untuk menjawab pertanyaan ini :

Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
  // ... do something with the culprits, i.e. elements which are not common

}

Penyebab : yaitu elemen-elemen yang tidak umum untuk keduanya Lists. Menentukan pelaku mana yang menjadi milik list1dan yang mana list2relatif mudah menggunakan CollectionUtils.intersection( list1, culprits )dan CollectionUtils.intersection( list2, culprits ).
Namun itu cenderung berantakan dalam kasus-kasus seperti {"a", "a", "b"} disjunctiondengan {"a", "b", "b"} ... kecuali ini bukan merupakan kegagalan dari perangkat lunak, tetapi melekat pada sifat seluk-beluk / ambiguitas tugas yang diinginkan.

Anda selalu dapat memeriksa kode sumber (l. 287) untuk tugas seperti ini, seperti yang diproduksi oleh para insinyur Apache. Salah satu manfaat menggunakan kode mereka adalah bahwa kode tersebut telah dicoba dan diuji secara menyeluruh, dengan banyak kasus tepi dan kasus yang diantisipasi dan ditangani. Anda dapat menyalin dan mengubah kode ini ke isi hati Anda jika perlu.


NB Saya awalnya kecewa karena tidak ada CollectionUtilsmetode yang menyediakan versi overload yang memungkinkan Anda untuk memaksakan sendiri Comparator(sehingga Anda dapat mendefinisikan kembali equalssesuai dengan tujuan Anda).

Tapi dari collections4 4.0 ada kelas baru, Equatoryang "menentukan kesetaraan antara objek tipe T". Pada pemeriksaan kode sumber collections4 CollectionUtils.java mereka tampaknya menggunakan ini dengan beberapa metode, tetapi sejauh yang saya bisa tahu ini tidak berlaku untuk metode di bagian atas file, menggunakan CardinalityHelperkelas ... yang termasuk disjunctiondan intersection.

Saya menduga bahwa orang-orang Apache belum sempat karena ini tidak sepele: Anda harus membuat sesuatu seperti kelas "AbstractEquatingCollection", yang alih-alih menggunakan elemen bawaannya equalsdan hashCodemetode harus menggunakan mereka dari Equatoruntuk semua metode dasar, seperti add, contains, dll NB bahkan ketika Anda melihat kode sumber, AbstractCollectiontidak melaksanakan add, juga tidak subclass abstrak seperti AbstractSet... Anda harus menunggu sampai kelas beton seperti HashSetdan ArrayListsebelum adddiimplementasikan. Cukup sakit kepala.

Sementara itu perhatikan ruang ini, kurasa. Solusi sementara yang jelas adalah membungkus semua elemen Anda dalam kelas pembungkus dipesan lebih dahulu yang menggunakan equalsdan hashCodeuntuk menerapkan jenis kesetaraan yang Anda inginkan ... kemudian memanipulasi Collectionsobjek pembungkus ini.

mike rodent
sumber
Juga, seseorang yang bijak mengatakan "Ketahui biaya ketergantungan"
Stanislaw Baranski
@StanislawBaranski Itu komentar yang menarik. Apakah ini saran agar orang tidak terlalu bergantung pada perpustakaan seperti itu? Ketika Anda menggunakan OS di komputer yang sudah menjadi lompatan besar iman bukan? Alasan saya senang menggunakan perpustakaan Apache adalah karena saya menganggapnya berkualitas sangat tinggi, dan berasumsi bahwa metode mereka mematuhi "kontrak" mereka dan telah diuji secara menyeluruh. Berapa banyak waktu yang Anda perlukan untuk mengembangkan kode Anda sendiri yang lebih Anda percayai? Menyalin kode dari perpustakaan Apache open-source dan meneliti itu mungkin sesuatu untuk dipikirkan ...
mike rodent
8

Jika kardinalitas item tidak masalah (artinya: elemen berulang dianggap sebagai satu), maka ada cara untuk melakukan ini tanpa harus mengurutkan:

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

Ini akan membuat Setdari masing-masing List, dan kemudian menggunakan HashSet's equalsmetode yang (tentu saja) mengabaikan pemesanan.

Jika kardinalitas penting, maka Anda harus membatasi diri pada fasilitas yang disediakan oleh List; Jawaban @ jschoen akan lebih pas dalam kasus itu.

Ishak
sumber
bagaimana jika listA = [a, b, c, c], dan listB = [a, b, c]. hasilnya akan benar, tetapi daftar tidak sama.
Nikolas
6

Mengubah daftar ke Multiset Guava bekerja sangat baik. Mereka dibandingkan terlepas dari pesanan mereka dan elemen duplikat diperhitungkan juga.

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));
Natix
sumber
6

Ini didasarkan pada solusi @cHao. Saya menyertakan beberapa perbaikan dan peningkatan kinerja. Ini berjalan kira-kira dua kali lebih cepat dari solusi sama dengan yang dipesan. Bekerja untuk semua jenis koleksi. Koleksi kosong dan null dianggap sama. Gunakan untuk keuntungan Anda;)

/**
 * 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;
}
DiddiZ
sumber
Anda dapat melewati final for-loop menggunakan penghitung jumlah. Penghitung jumlah akan menghitung jumlah total pada setiap tahap. Tambah penghitung jumlah di for-loop pertama, dan kurangi di for-loop kedua. Jika penghitung jumlah lebih besar dari 0, daftar tidak cocok, jika tidak mereka lakukan. Saat ini, dalam loop-terakhir Anda memeriksa apakah semua jumlah adalah nol atau dengan kata lain, jika jumlah semua jumlah adalah nol. Menggunakan jenis penghitung jumlah membalik cek ini, mengembalikan nilai true jika total jumlah adalah nol, atau salah sebaliknya.
SatA
IMO, perlu dilewati untuk-loop karena ketika daftar benar-benar cocok (skenario terburuk) for-loop menambahkan O yang tidak perlu (n).
SatA
@SatA sebenarnya, Anda dapat menghapus loop ke-3 tanpa penggantian apa pun. Loop kedua sudah kembali falseketika kunci tidak ada atau hitungnya menjadi negatif. Karena ukuran total kedua daftar cocok (ini telah diperiksa di muka), tidak mungkin untuk memiliki nilai bukan nol setelah loop kedua, karena tidak mungkin ada nilai positif untuk kunci tanpa nilai negatif untuk kunci lain.
Holger
@holger sepertinya Anda benar sekali. Sejauh yang saya tahu, loop ke-3 tidak diperlukan sama sekali.
SatA
@SatA ... dan dengan Java 8, ini dapat diimplementasikan secara ringkas, seperti dalam jawaban ini .
Holger
5

Pikirkan bagaimana Anda akan melakukan ini sendiri, tidak ada komputer atau bahasa pemrograman. Saya memberi Anda dua daftar elemen, dan Anda harus memberi tahu saya jika mereka mengandung elemen yang sama. Bagaimana Anda melakukannya?

Salah satu pendekatan, seperti yang disebutkan di atas, adalah untuk mengurutkan daftar dan kemudian pergi elemen-elemen untuk melihat apakah mereka sama (yang adalah apa List.equals artinya). Ini berarti Anda diizinkan mengubah daftar atau diizinkan menyalinnya - dan tanpa mengetahui tugasnya, saya tidak dapat mengetahui apakah salah satu dari keduanya diizinkan.

Pendekatan lain adalah melalui setiap daftar, menghitung berapa kali setiap elemen muncul. Jika kedua daftar memiliki jumlah yang sama di akhir, mereka memiliki elemen yang sama. Kode untuk itu adalah menerjemahkan setiap daftar ke peta elem -> (# of times the elem appears in the list)lalu memanggil equalskedua peta. Jika peta-peta itu ada HashMap, masing-masing terjemahan itu adalah operasi O (N), seperti perbandingannya. Itu akan memberi Anda algoritma yang cukup efisien dalam hal waktu, dengan biaya beberapa memori tambahan.

yshavit
sumber
5

Saya memiliki masalah yang sama dan menghasilkan solusi yang berbeda. Yang ini juga berfungsi ketika duplikat terlibat:

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;
}

Keuntungan dibandingkan dengan beberapa solusi lain:

  • kompleksitas kurang dari O (N²) (walaupun saya belum menguji kinerja sebenarnya dibandingkan dengan solusi dalam jawaban lain di sini);
  • keluar lebih awal;
  • memeriksa nol;
  • berfungsi bahkan ketika duplikat terlibat: jika Anda memiliki array [1,2,3,3]dan array lain, [1,2,2,3]sebagian besar solusi di sini memberi tahu Anda bahwa mereka sama ketika tidak mempertimbangkan pesanan. Solusi ini menghindari ini dengan menghapus elemen yang sama dari daftar sementara;
  • menggunakan persamaan semantik ( equals) dan bukan referensi persamaan (== );
  • tidak mengurutkan itens, sehingga mereka tidak perlu diurutkan implement Comparableagar solusi ini berfungsi.
Chalkos
sumber
3

Jika Anda tidak berharap untuk mengurutkan koleksi dan Anda membutuhkan hasil bahwa ["A" "B" "C"] tidak sama dengan ["B" "B" "A" "C"],

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

tidak cukup, Anda perlu memeriksa ukurannya juga:

    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);
}
Jaskey
sumber
2

Solusi yang memanfaatkan metode pengurangan CollectionUtils:

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;
  }
}
maxdanilkin
sumber
1

Jika Anda peduli tentang pesanan, maka gunakan metode sama dengan:

list1.equals(list2)

Jika Anda tidak peduli memesan maka gunakan ini

Collections.sort(list1);
Collections.sort(list2);      
list1.equals(list2)
Ramesh Kumar
sumber
4
Dia bilang dia tidak peduli tentang ketertiban.
mike rodent
0

Yang terbaik dari kedua dunia [@DiddiZ, @Chalkos]: yang ini terutama dibangun berdasarkan metode @Chalkos, tetapi memperbaiki bug (ifst.next ()), dan meningkatkan pemeriksaan awal (diambil dari @DiddiZ) serta menghilangkan kebutuhan untuk salin koleksi pertama (cukup hapus item dari salinan koleksi kedua).

Tidak memerlukan fungsi hashing atau penyortiran, dan memungkinkan awal ada pada ketidaksetaraan, ini adalah implementasi yang paling efisien. Itu kecuali Anda memiliki panjang koleksi dalam ribuan atau lebih, dan fungsi hashing yang sangat sederhana.

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;
}
jazzgil
sumber
Jika saya tidak salah, kompleksitas algoritma ini dalam skenario kasus bernilai (di mana daftar sama tetapi diurutkan dengan cara yang berlawanan) akan menjadi O (N * N!).
SatA
Sebenarnya, itu akan menjadi O (N * (N / 2)), karena dengan setiap iterasi, ukuran array berkurang.
jazzgil
0

Ini adalah cara alternatif untuk memeriksa persamaan daftar array yang dapat berisi nilai nol:

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);
}
Ayaz Alifov
sumber
Apa gunanya semua penyalinan antara daftar dan array ini?
Holger
0

Solusi saya untuk ini. Itu tidak begitu keren, tetapi bekerja dengan baik.

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();
}
Cícero Moura
sumber
-1

Dalam hal ini daftar {"a", "b"} dan {"b", "a"} sama. Dan {"a", "b"} dan {"b", "a", "c"} tidak sama. Jika Anda menggunakan daftar objek kompleks, ingatlah untuk menimpa metode sama dengan , seperti berisi semua menggunakannya di dalam.

if (oneList.size() == secondList.size() && oneList.containsAll(secondList)){
        areEqual = true;
}
Andrew
sumber
-1: memberikan jawaban yang salah dengan {"a", "a", "b"} dan {"a", "b", "b"}: periksa kode sumber untuk AbstractCollection.containsAll(). Anda harus mengizinkan untuk memiliki elemen duplikat seperti yang kita bicarakan Lists, bukan tentang Sets. Tolong lihat jawaban saya.
mike rodent