जावा में ऑर्डर किए गए सेट का कोई कार्यान्वयन?


98

यदि कोई व्यक्ति ऑब्जेक्टिव-सी से परिचित है तो सेट नामक एक संग्रह है NSOrderedSetजो सेट के रूप में कार्य करता है और उसके आइटम को ऐरे के रूप में एक्सेस किया जा सकता है ।

क्या जावा में ऐसा कुछ है?

मैंने सुना है कि एक संग्रह कहा जाता है LinkedHashMap, लेकिन मुझे सेट के लिए ऐसा कुछ नहीं मिला।


मैं c ++ में इसी तरह की समस्या पर काम कर रहा हूं। NSOrderedSet के साथ, क्या हम इसमें सम्मिलित किए गए क्रम में तत्वों तक पहुँच सकते हैं?
विनय

क्या आपको पता है कि C ++ में उपरोक्त कार्यक्षमता कैसे प्राप्त करें? i, ई सेट के रूप में कार्य कर रहा है और एरे के तत्वों के रूप में पहुँचा जा सकता है?
विनय

जवाबों:


118

LinkedHashSet वर्ग पर एक नज़र डालें

जावा डॉक्टर से :

हेश टेबल और सेट इट इंटरफेस की लिंक्ड सूची कार्यान्वयन, पूर्वानुमानित पुनरावृत्ति क्रम के साथ । यह कार्यान्वयन हैशसेट से इस मायने में भिन्न है कि यह अपनी सभी प्रविष्टियों के माध्यम से चलने वाली एक डबल-लिंक्ड सूची को बनाए रखता है। यह लिंक की गई सूची पुनरावृत्ति क्रम को परिभाषित करती है, जो वह क्रम है जिसमें तत्वों को सेट (सम्मिलन-क्रम) में डाला गया थाध्यान दें कि अगर किसी तत्व को सेट में फिर से डाला जाता है तो सम्मिलन आदेश प्रभावित नहीं होता है । (एक तत्व ई को एक सेट s में बदल दिया जाता है, अगर s.add (e) तब आह्वान किया जाता है जब s.contains (e) आह्वान के तुरंत पहले सच हो जाता है।)।


आपका बहुत बहुत धन्यवाद। यह तुच्छ लग LinkedHashMapरहा है लेकिन मैं इसे किसी भी तरह नहीं मिला है।
ऊको


9
इस उत्तर को इतने उभार क्यों मिल रहे हैं? यह सवाल का जवाब नहीं है, बिल्कुल। इसमें कोई फ़ंक्शन नहीं LinkedHashSetहै जो आपको यह पता लगाने की अनुमति देता है कि तत्व किस सूचकांक में है।
searchengine27

31

हर सेट में एक इटरेटर () होता है। एक सामान्य हैशसेट का इटरेटर काफी रैंडम होता है, एक ट्रीसैट इसे सॉर्ट क्रम से करता है, एक लिंक्डहाशसेट इटरेटर इंसर्ट क्रम से करता है।

आप किसी तत्व को LinkedHashSet में प्रतिस्थापित नहीं कर सकते, हालाँकि। आप एक को हटा सकते हैं और दूसरे को जोड़ सकते हैं, लेकिन नया तत्व मूल के स्थान पर नहीं होगा। LinkedHashMap में, आप एक मौजूदा कुंजी के लिए एक मूल्य को बदल सकते हैं, और फिर मूल्य अभी भी मूल क्रम में होंगे।

इसके अलावा, आप एक निश्चित स्थान पर नहीं डाल सकते हैं।

हो सकता है कि आप डुप्लिकेट डालने से बचने के लिए एक स्पष्ट जाँच के साथ एक ArrayList का बेहतर उपयोग करेंगे।


मैं विशिष्ट स्थिति पर तत्व सेट / प्राप्त करने में सक्षम होना चाहता हूं और उन्हें क्रम से प्राप्त करने के लिए मैंने उन्हें जोड़ा है। यह LinkedHashSetकाम करना चाहिए। उत्तर के लिए धन्यवाद
उको

11

जावा मानक एपीआई डॉक्टर पर एक नज़र डालें । ठीक बगल में LinkedHashMap, एक है LinkedHashSet। लेकिन ध्यान दें कि उन में क्रम डालने का क्रम है, तत्वों का प्राकृतिक क्रम नहीं। और आप केवल उस क्रम में पुनरावृत्ति कर सकते हैं, यादृच्छिक अभिगम नहीं (पुनरावृति चरणों को छोड़कर)।

वहाँ भी एक अंतरफलक है SortedSetद्वारा कार्यान्वित TreeSetऔर ConcurrentSkipListSet। दोनों अपने तत्वों के प्राकृतिक क्रम में पुनरावृत्ति की अनुमति देते हैं या ए Comparator, लेकिन यादृच्छिक अभिगम या सम्मिलन क्रम नहीं।

एक डेटा संरचना के लिए जिसमें इंडेक्स द्वारा दोनों की कुशल पहुंच है और कुशलता से सेट मानदंड को लागू कर सकते हैं, आपको एक स्किप सूची की आवश्यकता होगी , लेकिन जावा मानक एपीआई में उस कार्यक्षमता के साथ कोई कार्यान्वयन नहीं है, हालांकि मुझे यकीन है कि यह एक को ढूंढना आसान है इंटरनेट पर।


मैं आपकी टिप्पणी को गलत समझ सकता हूं लेकिन मैं इस धारणा के तहत था कि जावा 1.6 के बाद से स्किप सूचियों (जैसे, कहते हैं, समवर्तीSkipListSet आदि) के आधार पर कई डिफ़ॉल्ट संग्रह थे ।
टेक्टिकलकोडर

@ user988052: हाँ, लेकिन वे इंडेक्स द्वारा रैंडम एक्सेस को लागू नहीं करते हैं (हालाँकि स्किप लिस्ट की मेरी समझ कहती है कि यह संभव होना चाहिए), जो लगता है कि यूको चाहता है।
माइकल बॉर्गवर्ड

@MichaelBorgwardt जावा 6 और बाद में छोड़ें सूची कार्यान्वयन की एक जोड़ी शामिल है: ConcurrentSkipListMapऔर ConcurrentSkipListSet। दोनों प्राकृतिक क्रम या एक तुलनित्र के आधार पर एक प्रकार बनाए रखते हैं। मुझे समझ नहीं आ रहा है कि क्या वे आपके द्वारा चर्चा की गई रैंडम एक्सेस या ऑर्डर-ऑफ-एंट्री प्रदान करते हैं।
बेसिल बोर्ख

@ बासिलबोर्क: अच्छी खोज, और संपादन के लिए धन्यवाद। ओपी इंडेक्स तक पहुंच चाहता था, और अब जब मैंने इसे देखा और इसके बारे में सोचा, तो मुझे लगता है कि स्किप लिस्ट वास्तव में वह क्षमता नहीं है ...
माइकल बोर्गवर्ड

5

TreeSet का आदेश दिया है।

http://docs.oracle.com/javase/6/docs/api/java/util/TreeSet.html


यह सही जवाब है। LHSet के विपरीत, TreeSet java.util.SreadSet को लागू करता है।
वीवीवी

40
आदेश दिया और हल अलग चीजें हैं। ट्रीसेट को क्रमबद्ध किया गया है, आदेश नहीं दिया गया है
andrii

2
वास्तव में, आदेश सम्मिलन आदेश (जिस तरह से एक सूची) काम करता है, जबकि क्रमबद्ध कुछ मापदंडों के आधार पर तत्वों के बाद के आदेश को संदर्भित करता है।
कॉर्नेल मेसन

5

java.util.TreeSetउस औजार का उपयोग करके देखें SortedSet

डॉक्टर को उद्धृत करने के लिए:

"तत्वों को उनके प्राकृतिक ऑर्डरिंग का उपयोग करने का आदेश दिया जाता है, या सेट निर्माण समय पर प्रदान किए गए एक तुलनित्र द्वारा, जिसके आधार पर कंस्ट्रक्टर का उपयोग किया जाता है"

ध्यान दें कि समय लागत लॉग (n) को जोड़ने, हटाने और सम्‍मिलित है।

यदि आप सेट की सामग्री को ऐरे के रूप में एक्सेस करना चाहते हैं, तो आप इसे कर सकते हैं:

YourType[] array = someSet.toArray(new YourType[yourSet.size()]); 

इस सरणी को ट्रीसेट (प्राकृतिक या एक तुलनित्र द्वारा) के समान मानदंड के साथ क्रमबद्ध किया जाएगा, और कई मामलों में यह Arrays.sort () करने के बजाय एक फायदा होगा।


1
मैं अगर मैं पहला तत्व डाल ArrayList Ei में की तरह आदेश देने की जरूरत है cऔर फिर तत्व a:, जैसा कि मैंने पुनरावृति एक संग्रह से अधिक मैं उन्हें उसी क्रम में प्राप्त करना चाहते हैं c, aआदि
Uko

1

ट्रीसेट एक ऑर्डर किया गया सेट है, लेकिन आप आइटम इंडेक्स के माध्यम से एक्सेस नहीं कर सकते, बस इसके माध्यम से पुनरावृत्ति करें या शुरुआत / अंत तक जाएं।


ट्रीसेट के साथ आप बढ़ी हुई लागत में खर्च करेंगे। लिंक्डहाशसेट की लागत कम है।
कार्लोस

0

अगर हम स्किप-लिस्ट के सस्ते कार्यान्वयन के बारे में बात कर रहे हैं, तो मुझे आश्चर्य है कि बड़े ओ की अवधि में, इस ऑपरेशन की लागत क्या है:

YourType [] array = someSet.toArray (नया YourType [yourSet.size ()]);

मेरा मतलब है कि यह हमेशा पूरे सरणी निर्माण में फंस जाता है, इसलिए यह O (n) है:

java.util.Arrays#copyOf

1
यह इटरेटर की प्रदर्शन विशेषताओं और size()अंतर्निहित सेट की विधि पर निर्भर करता है । Iteration आमतौर पर होता है O(n), आकार आमतौर पर जहां इसे O(1)छोड़कर है । ConcurrentSkipListSetO(n)
इयान रॉबर्ट्स


0

आपको Google Guava की तरह एक अप्रत्यक्ष मानचित्र BiMapसे भी कुछ उपयोगिता मिल सकती है

ए के साथ BiMap, आप किसी भी अन्य ऑब्जेक्ट प्रकार के लिए बहुत कुशलता से एक इंटेगर (रैंडम इंडेक्स एक्सेस के लिए) मैप कर सकते हैं। BiMaps एक-से-एक हैं, इसलिए किसी भी दिए गए पूर्णांक में, सबसे अधिक, एक तत्व इसके साथ जुड़ा हुआ है, और किसी भी तत्व में एक से जुड़ा पूर्णांक है। यह दो HashTableउदाहरणों से बड़ी चतुराई से काम करता है, इसलिए यह मेमोरी को लगभग दोगुना कर देता है, लेकिन यह एक रिवाज की तुलना में बहुत अधिक कुशल है, Listजहां तक ​​प्रोसेसिंग होती है contains()( क्योंकि जो तब मिलता है जब किसी आइटम को यह जांचने के लिए जोड़ा जाता है कि यह पहले से मौजूद है) एक निरंतर समय है और समानांतर-अनुकूल संचालन जैसे HashSetकि एस, जबकि Listकार्यान्वयन एक बहुत धीमी है।


0

मुझे भी ऐसी ही समस्या का समाधान करना पड़ा था। मुझे एक ऑर्डर किए गए सेट की ज़रूरत नहीं थी, लेकिन तेज़ indexOf/ अधिक सूची के साथ contains। जैसा कि मुझे वहां कुछ भी नहीं मिला, मैंने खुद को लागू किया। यहां कोड है, यह दोनों को लागू करता है Setऔर List, हालांकि सभी बल्क सूची संचालन ArrayListसंस्करण के रूप में तेज़ नहीं हैं ।

अस्वीकरण: परीक्षण नहीं किया गया

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import java.util.Collection;
import java.util.Comparator;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import static java.util.Objects.requireNonNull;

/**
 * An ArrayList that keeps an index of its content so that contains()/indexOf() are fast. Duplicate entries are
 * ignored as most other java Set's do.
 */
public class IndexedArraySet<E> extends ArrayList<E> implements Set<E> {

    public IndexedArraySet() { super(); }

    public IndexedArraySet(Iterable<E> c) {
        super();
        addAll(c);
    }

    private HashMap<E, Integer> indexMap = new HashMap<>();

    private void reindex() {
        indexMap.clear();
        int idx = 0;
        for (E item: this) {
            addToIndex(item, idx++);
        }
    }

    private E addToIndex(E e, int idx) {
        indexMap.putIfAbsent(requireNonNull(e), idx);
        return e;
    }

    @Override
    public boolean add(E e) {
        if(indexMap.putIfAbsent(requireNonNull(e), size()) != null) return false;
        super.add(e);
        return true;
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        return addAll((Iterable<? extends E>) c);
    }
    public boolean addAll(Iterable<? extends E> c) {
        boolean rv = false;
        for (E item: c) {
            rv |= add(item);
        }
        return rv;
    }

    @Override
    public boolean contains(Object e) {
        return indexMap.containsKey(e);
    }

    @Override

    public int indexOf(Object e) {
        if (e == null) return -1;
        Integer i = indexMap.get(e);
        return (i == null) ? -1 : i;
    }

    @Override
    public int lastIndexOf(Object e) {
        return indexOf(e);
    }

    @Override @SuppressWarnings("unchecked")
    public Object clone() {
        IndexedArraySet clone = (IndexedArraySet) super.clone();
        clone.indexMap = (HashMap) indexMap.clone();
        return clone;
    }

    @Override
    public void add(int idx, E e) {
        if(indexMap.putIfAbsent(requireNonNull(e), -1) != null) return;
        super.add(idx, e);
        reindex();
    }

    @Override
    public boolean remove(Object e) {
        boolean rv;
        try { rv = super.remove(e); }
        finally { reindex(); }
        return rv;
    }

    @Override
    public void clear() {
        super.clear();
        indexMap.clear();
    }

    @Override
    public boolean addAll(int idx, Collection<? extends E> c) {
        boolean rv;
        try {
            for(E item : c) {
                // check uniqueness
                addToIndex(item, -1);
            }
            rv = super.addAll(idx, c);
        } finally {
            reindex();
        }
        return rv;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        boolean rv;
        try { rv = super.removeAll(c); }
        finally { reindex(); }
        return rv;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        boolean rv;
        try { rv = super.retainAll(c); }
        finally { reindex(); }
        return rv;
    }

    @Override
    public boolean removeIf(Predicate<? super E> filter) {
        boolean rv;
        try { rv = super.removeIf(filter); }
        finally { reindex(); }
        return rv;
    }

    @Override
    public void replaceAll(final UnaryOperator<E> operator) {
        indexMap.clear();
        try {
            int duplicates = 0;
            for (int i = 0; i < size(); i++) {
                E newval = requireNonNull(operator.apply(this.get(i)));
                if(indexMap.putIfAbsent(newval, i-duplicates) == null) {
                    super.set(i-duplicates, newval);
                } else {
                    duplicates++;
                }
            }
            removeRange(size()-duplicates, size());
        } catch (Exception ex) {
            // If there's an exception the indexMap will be inconsistent
            reindex();
            throw ex;
        }

    }

    @Override
    public void sort(Comparator<? super E> c) {
        try { super.sort(c); }
        finally { reindex(); }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.