2013-02-08 58 views
5

में retainAll का उपयोग करके कई सूचियों का छेड़छाड़ प्राप्त करें मुझे जावा पर कई सूचियों का चौराहे पाने में परेशानी हो रही है। क्या मैं कर रहा हूँ यह है: मैं (कहना देता है) पूर्णांक संख्या के 3 सूचियाँ:जावा

सूची 1: [2, 2, 2, 2, 5, 5]

सूची 2: [2 , 2, 103]

सूची 3: [2, 431]

मैं शेष सूचियों में से प्रत्येक का उपयोग कर पहले एक करने के लिए retainAll लागू करने हूँ:

list1.retainAll(list2); 
list1.retainAll(list3); 

और मैं इस हो रही है परिणाम:

List1: [2, 2, 2, 2]

लेकिन मैं इस एक पाने के लिए उम्मीद थी:

List1: [2]

... केवल तत्व सब के बाद से सूचियों शेयर एक 2 और नहीं चार 2.

है मैं जानता हूँ कि यह शायद retainAll समारोह की अपेक्षित व्यवहार है, लेकिन मैं परिणाम मैं उपर्युक्त प्राप्त करने की आवश्यकता।

कोई मदद?

संपादित करें: डुप्लीकेट को अस्वीकार करने के लिए हैशसेट का उपयोग करना या तो चाल नहीं करेगा। इस मामले में, उदाहरण के लिए:

सूची 1: [2, 2, 2, 2, 5, 5]

सूची 2: [2, 2, 103]

सूची 3: [2 , 2, 2, 431]

मैं का एक परिणाम प्राप्त करने की आवश्यकता:

सूची 1: [2, 2]

के बजाय (के बाद से सभी सूचियों 2 के कम से कम एक जोड़ी है)

सूची 1: [2]

+0

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

उत्तर

5

क्या इस विधि के बारे:

public static <T> Collection <T> intersect (Collection <? extends T> a, Collection <? extends T> b) 
{ 
    Collection <T> result = new ArrayList <T>(); 

    for (T t: a) 
    { 
     if (b.remove (t)) result.add (t); 
    } 

    return result; 
} 

public static void main (String [] args) 
{ 
    List <Integer> list1 = new ArrayList <Integer> (Arrays.<Integer>asList (2, 2, 2, 2, 5, 5)); 
    List <Integer> list2 = new ArrayList <Integer> (Arrays.<Integer>asList (2, 2, 103)); 
    List <Integer> list3 = new ArrayList <Integer> (Arrays.<Integer>asList (2, 431)); 

    System.out.println (intersect (list1, intersect (list2, list3))); 
} 
+1

यह वही करता है जो मैं चाहता हूं। यदि प्रत्येक सरणी पर संख्याओं की एक जोड़ी दिखाई देती है, तो यह दो संख्याओं के रूप में दिखाई देगी और न केवल एक के रूप में। – Multitut

0

एक सूची के बजाय आपको बैग, या मल्टीसेट नामक डेटा संरचना की आवश्यकता है। उदाहरण के लिए अपाचे कॉमन्स संग्रह पुस्तकालय एक में शामिल हैं:

http://commons.apache.org/collections/apidocs/org/apache/commons/collections/Bag.html#retainAll(java.util.Collection)

+1

'retainAll' विधि लिंक * * कार्डिनिटी का सम्मान नहीं करता है, जो वह पूरा करने की कोशिश कर रहा है। – ataylor

+0

कॉमन्स बैग में कार्यान्वयन करता है। * "इन तरीकों में से कई में निर्दिष्ट व्यवहार संग्रह द्वारा निर्दिष्ट व्यवहार के समान नहीं है।" * – Joni

+0

ओह, आप अमरूद के मल्टीसेट का संदर्भ लें। मैं इसके संदर्भ में हटा रहा हूं। – Joni

0

retainAll के साथ आप गलत जवाब मिल जाएगा के रूप में आप ने कहा। मैं आपको HashMapinteger/count जोड़ों को रखने और एक दूसरे की सूची को स्कैन करने और map को सीमित करने की सलाह दूंगा।

  1. list1 के मानों से map को पॉप्युलेट करें।
  2. एक दूसरे की सूची पर Iterate और min(# of intg in other_list, map.get(intg)) ले लो और उस मूल्य के साथ map अद्यतन करें।
  3. परिणाम map सभी सूचियों का चौराहे होगा।
2

यह समस्या एक मल्टीसेट डेटा संरचना के साथ आसान हल किया जा सकता। उदाहरण के लिए, यदि आप का उपयोग अमरूद के Multiset, आप का उपयोग Multisets.retainOccurrences()

2

मैं, शायद एक HashSetSet किसी तरह का प्रयोग करेंगे कर सकते हैं। वे डुप्लिकेट तत्व नहीं जोड़ेंगे, और उनके पास retainAll विधि है।

Set<Integer> uniqueNums = new HashSet<Integer>(list1); 
uniqueNums.retainAll(list2); 
uniqueNums.retainAll(list3); 

यहाँ Set के लिए javadocs है।

+0

धन्यवाद, लेकिन यह चाल नहीं करेगा। मैंने प्रश्न को अद्यतन किया है। – Multitut

0

यहां एक जैसा है जैसा आप पसंद करते हैं और यह रिकर्सिव है।

public static <T> List<T> intersect(List<T> c1, List<T> c2) { 
    List<T> inter = new ArrayList<>(c1); 
    inter.retainAll(c2); 
    return inter; 
} 

public static <T> List<T> intersect(List<T> first, List<T>... rest) { 
    if (rest.length == 0) 
     return first; 

    List<T> second = rest[0]; 

    first = intersect(first,second); 
    rest = Arrays.copyOfRange(rest, 1, rest.length); 

    return intersect(first, rest); 
}