Java ArrayList - अगर दो सूचियां समान हैं, तो मैं यह नहीं बता सकता हूं कि कोई बात नहीं है?


133

मेरे पास दो ArrayListप्रकार का है Answer(स्व-निर्मित वर्ग)।

मैं यह देखने के लिए दो सूचियों की तुलना करना चाहता हूं कि क्या उनमें समान सामग्री है, लेकिन बिना आदेश के कोई फर्क नहीं पड़ता।

उदाहरण:

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

List.equalsबताता है कि दो सूचियां समान हैं यदि उनमें समान आकार, सामग्री और तत्वों का क्रम है। मैं एक ही बात चाहता हूं, लेकिन बिना आदेश के कोई फर्क नहीं पड़ता।

क्या ऐसा करने के लिए एक सरल तरीका है? या क्या मुझे लूप के लिए नेस्टेड करने की आवश्यकता होगी, और दोनों सूचियों के प्रत्येक सूचकांक को मैन्युअल रूप से जांचना होगा?

नोट: मैं उन्हें ArrayListकिसी अन्य प्रकार की सूची से नहीं बदल सकता , उन्हें यह बने रहने की आवश्यकता है।


4
इस सवाल का जवाब देखें: stackoverflow.com/a/1075699/1133011
डेविड क्राउकम्प

List.containsAll (सूची) को जावा में देखें
साहिल जैन

जवाबों:


130

आप दोनों सूचियों का उपयोग करके सॉर्ट कर सकते हैं Collections.sort()और फिर समान विधि का उपयोग कर सकते हैं। एक बेहतर ढंग से बेहतर समाधान यह है कि पहले जांच लें कि क्या वे ऑर्डर करने से पहले समान लंबाई के हैं, यदि वे नहीं हैं, तो वे बराबर नहीं हैं, फिर क्रमबद्ध करें, फिर बराबर का उपयोग करें। उदाहरण के लिए यदि आपके पास स्ट्रिंग्स की दो सूचियाँ हैं तो यह कुछ इस तरह होगी:

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
बस याद रखें कि मूल सूची के क्रम को नष्ट न करें (जैसा कि Collections.sortकरता है) - यानी एक प्रति पारित करें।
२१:१० बजे अर्शजी

@ARS हाँ जो एक निश्चित साइड इफेक्ट है, लेकिन केवल अगर यह उनके विशेष मामले में मायने रखता है।
याकूब स्कोन

3
आप सिर्फ one = new ArrayList<String>(one); two = new ArrayList<String>(two);तर्कों को बर्बाद करने से बचने के लिए जोड़ सकते हैं ।
२१:१४ बजे अर्शजी

@jschoen कलेक्शन करने की कोशिश कर रहा है। Sort () मुझे यह त्रुटि दे रहा है: बाउंड मिसमैच: टाइप कलेक्शन का जेनेरिक मेथड सॉर्ट (लिस्ट <T>) आर्ग्युमेंट्स के लिए लागू नहीं है (ArrayList <Answer>)। अनुमानित प्रकार उत्तर बाध्य पैरामीटर के लिए मान्य विकल्प नहीं है <T तुलनात्मक <? सुपर टी >>
iaacp

3
दूसरे "अगर" फंक्शन के अंदर स्टेटमेंट को सरल बनाया जा सकता है if(one == null || two == null || one.size() != two.size()){ return false; }क्योंकि आप पहले से ही चेक कर रहे हैं कि क्या एक और दो दोनों अशक्त हैं
ह्यूगो

151

किसी भी सूची के लिए सबसे आसान तरीका होगा:

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

5
उसमे मज़ा कहाँ है। सभी गंभीरता में हालांकि यह शायद बेहतर समाधान है।
याकूब स्कोन नोव

67
इस पर निर्भर करता [a, b, c]है और [c, b, a, b]एक ही सामग्री के लिए माना जाता है। यह उत्तर कहता है कि वे करते हैं, लेकिन यह हो सकता है कि ओपी के लिए वे नहीं करते हैं (क्योंकि एक में एक डुप्लिकेट होता है और दूसरा नहीं होता है)। दक्षता मुद्दों के कुछ भी नहीं कहने के लिए।
यशवित

4
टिप्पणियों के आधार पर वृद्धि - System.out.println (((l1.size () == l2.size ()) && l2.containsAll (l1) && l1.containsAll (l2));
Nrj

8
@Nrj, [1,2,2] और [2,1,1] के बारे में क्या?
ROMANIA_engineer

3
इस दृष्टिकोण में O (n ^ 2) की जटिलता है। दो सूचियों पर विचार करें जो पूर्व के क्रम में हैं, उदाहरण के लिए: [1,2,3] और [3,2,1]। पहले तत्व के लिए इसे n तत्वों को स्कैन करना होगा, दूसरे n-1 तत्वों को और इसी तरह। तो जटिलता क्रम n ^ 2 की होगी। मुझे लगता है कि बेहतर तरीका छाँटना होगा और फिर बराबरी का उपयोग करना होगा। इसमें O (n * log (n))
puneet

90

अपाचे कॉमन्स संग्रह बचाव के लिए एक बार फिर से:

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

डॉक्स:

org.apache.commons.collections4.CollectionUtils

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

रिटर्न trueअगर if Collections में समान कार्डिनैलिटी वाले समान तत्व होते हैं।

अर्थात्, यदि a में e की कार्डिनैलिटी b में e की कार्डिनैलिटी के बराबर है प्रत्येक तत्व के लिए, में एक या बी

पैरामीटर:

  • a - पहला संग्रह, नहीं होना चाहिए null
  • b - दूसरा संग्रह, नहीं होना चाहिए null

रिटर्न: trueयदि संग्रह में समान कार्डिनैलिटी वाले समान तत्व हैं।


कार्यान्वयन कमोबेश DiddiZ के उत्तर के समान है।
user227353

ठीक है ... लेकिन दोषियों को पकड़ने के बारे में क्या है (ऐसे तत्व जो दो सूचियों के लिए सामान्य नहीं हैं) यदि उत्तर है false? मेरा जवाब देखिए।
माइक कृंतक

implementation 'org.apache.commons:commons-collections4:4.3'मुझे एक त्रुटि Caused by: com.android.builder.dexing.DexArchiveBuilderException: Failed to process पथ के साथ छोड़ दिया है ।
अलिटॉन ओलिवेरा

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

वाह, यह वास्तव में अन्य सभी समाधानों की तुलना में तेजी से प्रदर्शन पाकर आश्चर्यचकित था। और यह जल्दी आउट का समर्थन करता है।
दिदिज़

यह दूसरे लूप में शॉर्ट-सर्किट भी कर सकता है, यदि countऋणात्मक हो जाता है , तो लूप बॉडी को सरल बनाने के if(!counts.containsKey(item) || --counts.get(item).count < 0) return false;साथ-साथ, थ्री लूप को सरल बनाया जा सकता हैfor(Count c: counts.values()) if(c.count != 0) return false;
Holger

@ होलगर ने पहले कुछ पर विचार किया (शून्य को हिट करने पर गिनती को हटा दिया, जिसका प्रभाव समान होगा, लेकिन अंत में चेक को "वापसी चाहे countsखाली हो" में बदल दें), लेकिन अस्पष्ट नहीं करना चाहते थे मुख्य बिंदु: कि नक्शे का उपयोग करना मूल रूप से इसे O (N + M) समस्या में बदल देता है, और आपको प्राप्त होने वाली एकल सबसे बड़ी वृद्धि है।
cHao

@ cHao हाँ, आप पिछले वाले की तुलना में बेहतर समय जटिलता वाले समाधान की ओर इशारा करने के लिए श्रेय के पात्र हैं। मैं सिर्फ इसके बारे में सोचने के लिए हुआ था, क्योंकि पुनरावृत्तियों के बारे में हाल ही में इसी तरह का सवाल है। चूँकि हमारे पास अब जावा 8 भी है, इसलिए इसे पुनर्विचार करने लायक बनाया। यदि आप दूसरे लूप में शॉर्ट-सर्किट करते हैं, जब संख्या नकारात्मक हो जाती है, तो तीसरा लूप अप्रचलित हो जाता है। इसके अलावा, बॉक्सिंग से बचना एक दोधारी तलवार हो सकती है, नए के साथ Map.merge, बॉक्सेड पूर्णांकों का उपयोग सरल और अधिक उपयोग करने योग्य हो सकता है। इस उत्तर को भी देखें ...
Holger

10

मैं कहूंगा कि ये उत्तर एक चाल याद करते हैं।

बलोच, अपने आवश्यक, अद्भुत, संक्षिप्त प्रभावी जावा में , कहते हैं, आइटम 47 में, "पुस्तकालयों को जानें और उपयोग करें" शीर्षक, "संक्षेप में कहें, पहिया को सुदृढ़ न करें"। और वह कई बहुत स्पष्ट कारण देता है कि क्यों नहीं।

यहाँ कुछ उत्तर दिए गए हैं जो CollectionUtilsअपाचे कॉमन्स कलेक्शंस लाइब्रेरी में दिए गए तरीकों के बारे में बताते हैं लेकिन किसी ने भी इस सवाल का जवाब देने का सबसे सुंदर, सुरुचिपूर्ण तरीका नहीं देखा है :

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

}

Culprits : यानी जो तत्व दोनों के लिए आम नहीं हैं Lists। यह निर्धारित करना कि कौन से अपराधी हैं list1और कौन सा list2अपेक्षाकृत सीधा उपयोग कर रहा है CollectionUtils.intersection( list1, culprits )और CollectionUtils.intersection( list2, culprits )
हालाँकि यह {"a", "a", "b"} disjunctionजैसे {"a", "b", "b"} जैसे मामलों में अलग हो जाता है ... सिवाय इसके कि यह सॉफ्टवेयर की विफलता नहीं है, लेकिन वांछित कार्य की सूक्ष्मताओं / अस्पष्टताओं की प्रकृति के निहित है।

आप इस तरह के कार्य के लिए हमेशा स्रोत कोड (l 287) की जांच कर सकते हैं , जैसा कि अपाचे इंजीनियरों द्वारा उत्पादित किया गया है। उनके कोड का उपयोग करने का एक लाभ यह है कि इसे पूरी तरह से आजमाया और परखा जाएगा, जिसमें कई किनारे के मामले और गेटेक प्रत्याशित और निपटाए जाएंगे। यदि आवश्यक हो तो आप इस कोड को अपने दिल की सामग्री पर कॉपी और ट्विक कर सकते हैं।


नायब I पहली बार निराश हुआ कि कोई भी CollectionUtilsतरीका एक अतिभारित संस्करण प्रदान नहीं करता है जो आपको अपना स्वयं का थोपने में सक्षम बनाता है Comparator(ताकि आप equalsअपने उद्देश्यों के अनुरूप पुनर्परिभाषित कर सकें )।

लेकिन संग्रह 4 4.0 से एक नया वर्ग है, Equatorजो "टाइप टी की वस्तुओं के बीच समानता को निर्धारित करता है"। Collection4 CollectionUtils.java के स्रोत कोड की जांच करने पर वे कुछ विधियों के साथ इसका उपयोग करते प्रतीत होते हैं, लेकिन जहां तक ​​मैं यह बता सकता हूं कि यह CardinalityHelperकक्षा के उपयोग से फ़ाइल के शीर्ष पर मौजूद तरीकों पर लागू नहीं है ... जो शामिल disjunctionऔर intersection

मुझे लगता है कि अपाचे लोगों को इसके आसपास अभी तक नहीं मिला है क्योंकि यह गैर-तुच्छ है: आपको "AbstractEquatingCollection" वर्ग की तरह कुछ बनाना होगा, जो इसके तत्वों के अंतर्निहित equalsऔर hashCodeतरीकों का उपयोग करने के बजाय उन का उपयोग करना होगा। की Equatorतरह के रूप में सभी बुनियादी तरीकों, के लिए add, containsआदि नायब वास्तव में जब आप स्रोत कोड को देखो, AbstractCollectionको लागू नहीं करता है add, और न ही इस तरह के रूप में अपनी सार उपवर्गों करना AbstractSet... आप इस तरह के रूप में ठोस वर्ग तक इंतजार करना पड़ता है HashSetऔर ArrayListइससे पहले कि addलागू किया गया है। काफी सिरदर्द।

इस समय में इस स्थान को देखो, मुझे लगता है। स्पष्ट अंतरिम समाधान एक bespoke आवरण वर्ग में अपने सभी तत्वों को लपेटना होगा जो उपयोग करता है equalsऔर hashCodeजिस तरह की समानता आप चाहते हैं उसे लागू करने के लिए ... फिर Collectionsइन आवरण वस्तुओं का हेरफेर करें।


इसके अलावा, किसी ने कहा कि "निर्भरता की लागत को जानें"
स्टैनिस्लाव बारांस्की

@StanislawBaranski यह एक दिलचस्प टिप्पणी है। क्या यह एक सुझाव है कि किसी को इस तरह के पुस्तकालयों पर निर्भर नहीं होना चाहिए? जब आप पहले से ही विश्वास की एक बड़ी छलांग कंप्यूटर पर एक ओएस का उपयोग करते हैं, तो क्या यह नहीं है? मैं अपाचे पुस्तकालयों का उपयोग करने के लिए खुश हूं, क्योंकि मैं उन्हें वास्तव में बहुत उच्च गुणवत्ता के लिए ले जाता हूं, और यह मानता हूं कि उनके तरीके उनके "अनुबंध" का अनुपालन करते हैं और पूरी तरह से परीक्षण किए गए हैं। आप अपना खुद का कोड विकसित करने में कितना समय लेंगे, जिस पर आपने अधिक भरोसा किया है? खुले स्रोत अपाचे पुस्तकालयों से कोड की नकल करना और इसकी छानबीन करना कुछ सोचने के बारे में हो सकता है ...
माइक कृंतक

8

यदि वस्तुओं की कार्डिनैलिटी मायने नहीं रखती है (मतलब: दोहराया तत्वों को एक के रूप में माना जाता है), तो ऐसा करने का एक तरीका है बिना इसे सॉर्ट किए:

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

यह एक बनाएगा Setप्रत्येक से बाहर Listहै, और फिर उपयोग करने HashSetकी equalsविधि है जो की उपेक्षा (बेशक) आदेश।

यदि कार्डिनैलिटी मायने रखती है, तो आपको अपने द्वारा दी गई सुविधाओं तक ही सीमित रहना चाहिए List; @ jschoen का जवाब उस मामले में अधिक उपयुक्त होगा।


क्या होगा अगर listA = [a, b, c, c], और listB = [a, b, c]। परिणाम सही होगा, लेकिन सूची बराबर नहीं हैं।
निकोलस

6

गुवा की मल्टीसेट में सूचियों को बदलना बहुत अच्छी तरह से काम करता है। उनके आदेश की परवाह किए बिना उनकी तुलना की जाती है और डुप्लिकेट तत्वों को भी ध्यान में रखा जाता है।

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

यह @cHao समाधान पर आधारित है। मैंने कई सुधार और प्रदर्शन सुधार शामिल किए। यह लगभग समान रूप से दो बार तेजी से बराबर-आदेश-कॉपी समाधान चलाता है। किसी भी संग्रह प्रकार के लिए काम करता है। खाली संग्रह और अशक्त को समान माना जाता है। अपने लाभ के लिए उपयोग करें;)

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

आप सम-काउंटर का उपयोग करके अंतिम फॉर-लूप को छोड़ सकते हैं। योग काउंटर प्रत्येक चरण में कुल गणना करेगा। पहले फॉर-लूप में योग काउंटर बढ़ाएं, और दूसरे फॉर-लूप में इसे घटाएं। यदि योग काउंटर 0 से अधिक है, तो सूची मेल नहीं खाती, अन्यथा वे करते हैं। वर्तमान में, अंतिम लूप के लिए आप जांचते हैं कि सभी गणना शून्य हैं या दूसरे शब्दों में, यदि सभी गणनाओं का योग शून्य है। सम काउंटर काउंटर प्रकार का उपयोग करना इस चेक को उलट देता है, अगर कुल की संख्या शून्य है, या अन्यथा अन्यथा सच है।
शनि

IMO, यह लंघन के लायक है कि जब से सूचियों का मिलान (सबसे खराब स्थिति) होता है तब से लूप के लिए लूप एक और अनावश्यक O (n) जोड़ता है।
शनि

@ सता वास्तव में, आप बिना किसी प्रतिस्थापन के तीसरे लूप को हटा सकते हैं। दूसरा लूप पहले ही वापस आ जाता है falseजब कोई कुंजी मौजूद नहीं होती है या उसकी गिनती नकारात्मक हो जाती है। चूंकि दोनों सूचियों का कुल आकार मेल खाता है (यह ऊपर की ओर जांचा गया है), दूसरे लूप के बाद गैर-शून्य मान होना असंभव है, क्योंकि एक कुंजी के लिए नकारात्मक मान के बिना कुंजी के लिए सकारात्मक मान नहीं हो सकते।
होल्गर

@ छेद ऐसा लगता है कि आप बिल्कुल सही हैं। जहाँ तक मैं बता सकता हूँ, 3 लूप बिल्कुल भी आवश्यक नहीं है।
शनि

@ सता ... और जावा 8 के साथ, इसे इस उत्तर की तरह, संक्षिप्त रूप से लागू किया जा सकता है ।
होल्गर

5

सोचें कि आप खुद ऐसा कैसे करेंगे, एक कंप्यूटर या प्रोग्रामिंग भाषा अनुपस्थित है। मैं आपको तत्वों की दो सूची देता हूं, और आपको मुझे बताना होगा कि क्या वे समान तत्व हैं। आपको इसे कैसे करना होगा?

एक दृष्टिकोण, जैसा कि ऊपर उल्लेख किया गया है, सूचियों को क्रमबद्ध करना है और फिर तत्व-दर-तत्व यह देखने के लिए जाना है कि क्या वे समान हैं (जो ऐसा List.equalsकरता है)। इसका मतलब यह है कि या तो आपको सूचियों को संशोधित करने की अनुमति है या आपको उन्हें कॉपी करने की अनुमति है - और असाइनमेंट को जाने बिना, मुझे यह नहीं पता चल सकता है कि दोनों में से किसी को भी अनुमति दी गई है।

एक और दृष्टिकोण प्रत्येक सूची के माध्यम से जाना होगा, यह गिनाएगा कि प्रत्येक तत्व कितनी बार प्रकट होता है। यदि दोनों सूचियों के अंत में एक ही मायने रखता है, तो उनके पास समान तत्व हैं। उस कोड को प्रत्येक सूची को मानचित्र के रूप में बदलना होगा elem -> (# of times the elem appears in the list)और फिर equalsदो मानचित्रों पर कॉल करना होगा। यदि नक्शे हैं HashMap, तो उन अनुवादों में से प्रत्येक एक ओ (एन) ऑपरेशन है, जैसा कि तुलना है। यह आपको कुछ अतिरिक्त मेमोरी की कीमत पर समय के संदर्भ में एक बहुत ही कुशल एल्गोरिदम देने जा रहा है।


5

मुझे यही समस्या थी और एक अलग समाधान के साथ आया था। यह भी काम करता है जब डुप्लिकेट शामिल होते हैं:

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

कुछ अन्य समाधानों की तुलना में लाभ:

  • ओ (एन than) जटिलता से कम (हालांकि मैंने परीक्षण नहीं किया है कि यह अन्य उत्तरों में समाधान की तुलना में वास्तविक प्रदर्शन है);
  • जल्दी बाहर निकलता है;
  • अशक्त के लिए जाँच;
  • डुप्लिकेट के शामिल होने पर भी काम करता है: यदि आपके पास एक सरणी है [1,2,3,3]और दूसरा सरणी [1,2,2,3]यहां सबसे अधिक समाधान बताता है कि वे ऑर्डर नहीं होने पर समान हैं। यह समाधान अस्थायी सूचियों से समान तत्वों को निकालकर इससे बचता है;
  • शब्दार्थ समानता का उपयोग करता है ( equals) और संदर्भ समानता का नहीं ( ==);
  • इट्स सॉर्ट नहीं करता है, इसलिए उन्हें implement Comparableइस समाधान के लिए काम करने के लिए सॉर्टेबल (बाय ) होने की आवश्यकता नहीं है ।

3

यदि आप संग्रह को क्रमबद्ध करने की आशा नहीं करते हैं और आपको परिणाम की आवश्यकता है कि ["A" B "" C "] [" B "" B "" A "" C "] के बराबर नहीं है, तो"

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

पर्याप्त नहीं है, आपको आकार की भी जाँच करने की आवश्यकता है:

    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

समाधान जो संग्रह का लाभ उठाता है विधि घटाना:

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

यदि आप आदेश की परवाह करते हैं, तो बस बराबर विधि का उपयोग करें:

list1.equals(list2)

अगर आपको ऑर्डर की परवाह नहीं है तो इसका इस्तेमाल करें

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

4
वह कहता है कि उसे आदेश की परवाह नहीं है
माइक कृंतक

0

दोनों दुनिया के सर्वश्रेष्ठ [@DiddiZ, @Chalkos]: यह मुख्य रूप से @Chalkos विधि पर बनाता है, लेकिन एक बग (ifst.next ()) को ठीक करता है, और प्रारंभिक चेक (@DiddiZ से लिया गया) में सुधार करता है और साथ ही आवश्यकता को हटाता है पहले संग्रह की प्रतिलिपि बनाएँ (बस दूसरे संग्रह की प्रतिलिपि से आइटम निकालता है)।

एक हैशिंग फ़ंक्शन या सॉर्टिंग की आवश्यकता नहीं है, और असमान समानता पर एक प्रारंभिक अस्तित्व को सक्षम करना, यह अभी तक सबसे कुशल कार्यान्वयन है। जब तक कि आपके पास हजारों या अधिक में संग्रह की लंबाई नहीं है, और एक बहुत ही सरल हैशिंग फ़ंक्शन है।

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

यदि मैं गलत नहीं हूँ, तो इस एल्गोरिथ्म की जटिलता एक मामले के परिदृश्य में (जहाँ सूचियाँ बराबर हैं लेकिन विपरीत तरीके से क्रमबद्ध हैं) O (N * N!) होगी।
शनि

वास्तव में, यह O (N * (N / 2)) होगा, जैसा कि प्रत्येक पुनरावृत्ति के साथ, सरणी का आकार घट जाता है।
जाजगिल

0

यह सरणी सूचियों की समानता की जांच करने का एक वैकल्पिक तरीका है जिसमें शून्य मान हो सकते हैं:

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

सूचियों और सरणियों के बीच इस सभी नकल की बात क्या है?
होल्गर

0

इसके लिए मेरा समाधान। यह इतना अच्छा नहीं है, लेकिन अच्छी तरह से काम करता है।

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

उस स्थिति में {"a", "b"} और {"b", "a" समान हैं। और {"a", "b"} और {"b", "a", "c"} समान नहीं हैं। यदि आप जटिल वस्तुओं की सूची का उपयोग करते हैं, तो समतुल्य विधि को ओवरराइड करना याद रखें , क्योंकि इसमें सभी का उपयोग होता है।

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

-1: गलत उत्तर देता है {"a", "a", "b"} और {"a", "b", "b"}: के लिए स्रोत कोड देखें AbstractCollection.containsAll()। आपको डुप्लिकेट तत्वों को रखने की अनुमति देनी होगी, जैसे हम बात कर रहे हैं Lists, के बारे में नहीं Sets। कृपया मेरा उत्तर देखें।
माइक कृंतक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.