क्या कोई सम्मिलन आदेश सेट करना है जो सूची को भी लागू करता है?


85

मैं के एक कार्यान्वयन खोजने की कोशिश कर रहा हूँ java.util.Listऔर java.util.Setजावा में एक ही समय में। मैं चाहता हूं कि यह वर्ग केवल अद्वितीय तत्वों (के रूप में Set) की अनुमति दे और उनके आदेश (जैसे List) को संरक्षित करे । क्या यह JDK 6 में मौजूद है?

यह महत्वपूर्ण है List<T>#add(int, T)ताकि मैं एक विशिष्ट स्थिति में सम्मिलित हो सकूं।


क्या आप इसका मतलब है कि उनके सम्मिलन आदेश या कुछ आदेश को परिभाषित करते हैं Comparator? क्या आप भी Listइंटरफ़ेस के शब्दार्थ चाहते हैं ?

जवाबों:


207

TreeSetतत्व क्रम द्वारा हल किया गया है; LinkedHashSetनिवेशन क्रम बनाए रखता है। उम्मीद है कि उनमें से एक आप के बाद क्या था।

आपने निर्दिष्ट किया है कि आप एक अनियंत्रित स्थान पर सम्मिलित होना चाहते हैं , मुझे संदेह है कि आपको अपना स्वयं का लिखना होगा - बस एक ए HashSet<T>और ए युक्त क्लास बनाएं ArrayList<T>; आइटम जोड़ते समय, जांचें कि सूची में जोड़ने से पहले वह सेट में है या नहीं।

वैकल्पिक रूप से अपाचे के कॉमन्स-संग्रह 4 ऑफ़र ListOrderedSetऔर SetUniqueList, जो समान रूप से व्यवहार करते हैं और दी गई आवश्यकताओं को पूरा करना चाहिए।



12

क्या आपको पसंद है LinkedHashSet? यह प्रविष्टि के क्रम को सुरक्षित रखता है, लेकिन डुप्लिकेट की अनुमति नहीं देता है।

IMHO, इसकी एक असामान्य आवश्यकता है लेकिन आप डुप्लिकेट के बिना एक सूची लिख सकते हैं।

class SetList<T> extends ArrayList<T> {
    @Override
    public boolean add(T t) {
        return !super.contains(t) && super.add(t);
    }

    @Override
    public void add(int index, T element) {
        if (!super.contains(element)) super.add(index, element);
    }

    @Override
    public boolean addAll(Collection<? extends T> c) {
        boolean added = false;
        for (T t : c)
            added |= add(t);
        return added;
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> c) {
        boolean added = false;
        for (T t : c)
            if (!super.contains(t)) {
                super.add(index++, t);
                added = true;
            }
        return added;
    }
}

यह Listइंटरफ़ेस को लागू नहीं करता है, इस प्रश्न के लिए मेरे परिवर्तन देखें
yegor256

2
stackoverflow.com/a/8185105/253468 बेहतर दिखता है क्योंकि इसमें O(n)सम्मिलन की जटिलता नहीं है , एक ट्रेडऑफ़ है जिसे दोहरे भंडारण और O(log(n))सम्मिलित ऑपरेशन के बीच विचार करना है।
ट्विस्टस्ट्रीम

8

आप लागू नहीं कर सकते Listऔर Setअनुबंध उल्लंघन के बिना एक ही बार में। उदाहरण के लिए, Set.hashCodeअनुबंध देखें:

किसी सेट के हैश कोड को सेट के तत्वों के हैश कोड के योग के रूप में परिभाषित किया जाता है, जहाँ शून्य तत्व के हैश कोड को शून्य माना जाता है।

दूसरी ओर यहाँ अनुबंध List.hashCode:

किसी सूची का हैश कोड निम्नलिखित गणना के परिणाम के रूप में परिभाषित किया गया है:

int hashCode = 1;
for (E e : list)
    hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());

इसलिए एकल वर्ग को लागू करना असंभव है जो दोनों अनुबंधों को पूरा करने की गारंटी देता है। equalsकार्यान्वयन के लिए एक ही समस्या है।


4

यदि आप अपने आप को JDK 6 तक सीमित नहीं करेंगे, तो आप Apache सामान्य संग्रह लाइब्रेरी का उपयोग कर सकते हैं, जो आपकी ज़रूरत के लिए सटीक मिलान प्रदान करता है - ListOrderbSet । यह पसंद है Listऔर Setएक साथ संयुक्त है :)


माइनस द Listइंटरफ़ेस
लेटरलफ्रैक्टल

0

मुझे इसी तरह की समस्या थी, इसलिए मैंने अपना लिखा। देखें यहाँIndexedArraySetफैली हुई है ArrayListऔर लागू करता Setहै, इसलिए यह सभी कार्यों कि आप की आवश्यकता का समर्थन करना चाहिए। ध्यान दें कि कैन के बीच के स्थानों में तत्वों को सम्मिलित करना ArrayListबड़ी सूचियों के लिए धीमा हो सकता है क्योंकि सभी निम्नलिखित तत्वों को स्थानांतरित करने की आवश्यकता होती है। मेरा IndexedArraySetवह परिवर्तन नहीं है।


0

एक अन्य विकल्प ( Listइंटरफ़ेस की आवश्यकता शून्य ) अमरूद का है ImmutableSet, जो सम्मिलन आदेश को संरक्षित करता है। से उनके विकि पृष्ठ :

सॉर्ट किए गए संग्रहों को छोड़कर, ऑर्डर निर्माण समय से संरक्षित है। उदाहरण के लिए,

ImmutableSet.of("a", "b", "c", "a", "d", "b")

आदेश "ए", "बी", "सी", "डी" में अपने तत्वों पर पुनरावृति करेगा।

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