क्या जावा में दो स्ट्रिंग सेट को संयोजित करने का एक बेहतर तरीका है?


90

मुझे अनावश्यक जानकारी को फ़िल्टर करते समय दो स्ट्रिंग सेट को संयोजित करने की आवश्यकता है, यह वह समाधान है जिसके साथ मैं आया था, क्या कोई बेहतर तरीका है जिसे कोई भी सुझा सकता है? शायद कुछ है कि मैं अनदेखी में बनाया? गूगल के साथ कोई भाग्य नहीं था।

Set<String> oldStringSet = getOldStringSet();
Set<String> newStringSet = getNewStringSet();

for(String currentString : oldStringSet)
{
    if (!newStringSet.contains(currentString))
    {
        newStringSet.add(currentString);
    }
}

जवाबों:


116

चूंकि Setइसमें डुप्लिकेट प्रविष्टियाँ नहीं हैं, इसलिए आप दोनों को जोड़ सकते हैं:

newStringSet.addAll(oldStringSet);

इससे कोई फर्क नहीं पड़ता कि आप दो बार चीजों को जोड़ते हैं, सेट में केवल एक बार तत्व शामिल होगा ... उदाहरण के लिए containsविधि का उपयोग करके जांच करने की कोई आवश्यकता नहीं है ।


88

आप इसे इस एक-लाइनर का उपयोग करके कर सकते हैं

Set<String> combined = Stream.concat(newStringSet.stream(), oldStringSet.stream())
        .collect(Collectors.toSet());

एक स्थिर आयात के साथ यह और भी अच्छा लग रहा है

Set<String> combined = concat(newStringSet.stream(), oldStringSet.stream())
        .collect(toSet());

एक और तरीका है फ्लैटपाइप विधि का उपयोग करना :

Set<String> combined = Stream.of(newStringSet, oldStringSet).flatMap(Set::stream)
        .collect(toSet());

इसके अलावा किसी भी संग्रह को आसानी से एक तत्व के साथ जोड़ा जा सकता है

Set<String> combined = concat(newStringSet.stream(), Stream.of(singleValue))
        .collect(toSet());

यह AddAll से बेहतर कैसे है?
केकेलाला

7
@ केकेला, आपकी आवश्यकताओं का निर्धारण करेगा जो बेहतर है। addAllधाराओं के बीच और उपयोग करने का मुख्य अंतर है: • उपयोग करने set1.addAll(set2)से भौतिक रूप से सामग्री को बदलने का दुष्प्रभाव होगा set1। • हालांकि, स्ट्रीम का उपयोग करने से हमेशा Setमूल सेट इंस्टेंसेस को संशोधित किए बिना दोनों सेट की सामग्री को शामिल करने का एक नया उदाहरण होगा। IMHO यह उत्तर बेहतर है क्योंकि यह मूल सेट के अप्रत्याशित परिवर्तनों के लिए साइड-इफेक्ट्स और संभावित से बचता है अगर इसे मूल सामग्री की अपेक्षा करते हुए कहीं और इस्तेमाल किया जाए। HTH
edwardsmatt

1
इससे इम्यूटेबल सेट्स को सपोर्ट करने का भी फायदा है। देखें: docs.oracle.com/javase/8/docs/api/java/util/…
edwardsmatt


12

परिभाषा से सेट में केवल अनन्य तत्व होते हैं।

Set<String> distinct = new HashSet<String>(); 
 distinct.addAll(oldStringSet);
 distinct.addAll(newStringSet);

अपना कोड बढ़ाने के लिए आप उसके लिए एक सामान्य विधि बना सकते हैं

public static <T> Set<T> distinct(Collection<T>... lists) {
    Set<T> distinct = new HashSet<T>();

    for(Collection<T> list : lists) {
        distinct.addAll(list);
    }
    return distinct;
}

6

यदि आप अमरूद का उपयोग कर रहे हैं तो आप अधिक लचीलापन प्राप्त करने के लिए एक बिल्डर का उपयोग कर सकते हैं:

ImmutableSet.<String>builder().addAll(someSet)
                              .addAll(anotherSet)
                              .add("A single string")
                              .build();

4

बस उपयोग करें newStringSet.addAll(oldStringSet)। डुप्लिकेट की जांच करने की आवश्यकता नहीं है क्योंकि Setकार्यान्वयन पहले से ही ऐसा करता है।




2

उपयोग boolean addAll(Collection<? extends E> c)
जोड़ता इस सेट करने के लिए निर्दिष्ट संग्रह में सभी तत्त्व अगर वे पहले से ही मौजूद है (वैकल्पिक आपरेशन) नहीं कर रहे हैं। यदि निर्दिष्ट संग्रह भी एक सेट है, तो addAll ऑपरेशन प्रभावी रूप से इस सेट को संशोधित करता है ताकि इसका मान दो सेटों का मिलन हो। यदि कार्रवाई जारी है, तो निर्दिष्ट संग्रह को संशोधित करने पर इस ऑपरेशन का व्यवहार अपरिभाषित है।

newStringSet.addAll(oldStringSet)

2

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

Set<String> newStringSet = getNewStringSet();
Set<String> oldStringSet = getOldStringSet();

Set<String> myResult;
if(oldStringSet.size() > newStringSet.size()){
    oldStringSet.addAll(newStringSet);
    myResult = oldStringSet;
} else{
    newStringSet.addAll(oldStringSet);
    myResult = newStringSet;
}

इस तरह, यदि आपके नए सेट में 10 तत्व हैं और आपके पुराने सेट में 100 000 हैं, तो आप 100 000 के बजाय केवल 10 ऑपरेशन करते हैं।


यह एक बहुत अच्छा तर्क है कि मैं कल्पना नहीं कर सकता कि यह मुख्य addAll पद्धति पैरामीटर में क्यों नहीं है, जैसेpublic boolean addAll(int index, Collection<? extends E> c, boolean checkSizes)
Gaspar

मैं स्वयं विनिर्देश के कारण अनुमान लगाता हूं: निर्दिष्ट संग्रह में सभी तत्वों को इस संग्रह में जोड़ता है । आपके पास वास्तव में एक और तरीका हो सकता है, लेकिन यह काफी भ्रामक होगा यदि यह उसी विनिर्देशन का पालन नहीं करता है जो इसे ओवरलोड करता है।
रिकोला

हां, मैं अन्य विधि को ओवरलोडिंग कह रहा था कि एक
Gaspar

2

यदि आप अपाचे कॉमन का उपयोग कर रहे हैं, तो SetUtilsकक्षा का उपयोग करेंorg.apache.commons.collections4.SetUtils;

SetUtils.union(setA, setB);

ध्यान दें कि यह एक रिटर्न है SetView, जो अपरिवर्तनीय है।
jaco0646

2
Set.addAll()

यदि वे पहले से मौजूद नहीं हैं तो वैकल्पिक संग्रह में सभी तत्वों को जोड़ता है (वैकल्पिक संचालन)। यदि निर्दिष्ट संग्रह भी एक सेट है, तो addAll ऑपरेशन प्रभावी रूप से इस सेट को संशोधित करता है ताकि इसका मान दो सेटों का मिलन हो

newStringSet.addAll(oldStringSet)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.