2008-11-06 11 views
72

मुझे SortedSet के बारे में पता है, लेकिन मेरे मामले में मुझे ऐसा कुछ चाहिए जो List लागू करता है, और Set नहीं। तो क्या एपीआई या अन्य जगहों पर वहां कोई कार्यान्वयन है?क्या वहां कोई डुप्लिकेट सूची कार्यान्वयन नहीं है?

मुझे खुद को लागू करना मुश्किल नहीं होना चाहिए, लेकिन मुझे लगा कि लोगों को पहले यहां क्यों नहीं पूछना चाहिए?

+0

सूची को लागू करने की आवश्यकता क्यों है? समूह सूचियों की तरह पुनरावृत्त हैं, इसलिए मुझे लगता है कि प्राप्त करने की विधि किसी अन्य कारण के लिए सूची लागू कर रही है। – Rob

+0

@Rob यह सही है, यह एक बाहरी मांग है, और डेटा संरचना में एक से अधिक सूची का नरक शामिल है। – Yuval

+0

यदि उपयोगकर्ता एक सूची चाहता है, तो यह स्पष्ट है कि लिस्ट इंटरफ़ेस की विधियों की आवश्यकता है जो एसईटी इंटरफ़ेस मौजूद नहीं हैं ... – marcolopes

उत्तर

75

ऐसा करने के लिए मानक पुस्तकालय में कोई जावा संग्रह नहीं है। LinkedHashSet<E>List के समान क्रमबद्ध करने के लिए संरक्षित करता है, हालांकि, यदि आप List में अपना सेट लपेटते हैं तो आप List के रूप में इसका उपयोग करना चाहते हैं तो आपको वह अर्थशास्त्र मिलेगा जो आप चाहते हैं। SetUniqueList/SetUniqueList<E>:

वैकल्पिक रूप से, Commons Collections (या commons-collections4, जेनेरिक वर्जन के लिए) जो कि आप पहले से ही चाहते हैं करता है एक List है।

+5

कॉमन्स क्लास बिल्कुल वही है जो मुझे चाहिए, लेकिन मेरे मालिक ने मुझे अंततः इसे लागू करने के लिए कहा। वैसे भी 10x! – Yuval

+3

आह ठीक है, पहिया को फिर से शुरू करने की तरह कुछ भी नहीं! अगर आप फिर से जरूरत आती है, तो आपको पता चलेगा। संग्रह 15 चारों ओर लात मारने के लिए एक बहुत उपयोगी चीज है; मल्टीमैप्स विशेष रूप से किसी के दर्द को कम करने के लिए स्वयं को लागू करने में समाप्त होता है। – Calum

+19

@ स्काफमैन: वह वास्तव में बेवकूफ नहीं है, लेकिन कभी-कभी वह चाल बनाता है ... अच्छा, अजीब। वैसे भी, मैं उत्पाद में बग पेश नहीं कर रहा हूं। आज के बाजार में, यदि आप मेरी बात प्राप्त करते हैं, तो मैं अपने काम से खुश हूं और स्लैम दरवाजे और जला पुलों को नहीं देख रहा हूं। – Yuval

4

क्यों प्रकार की तरह एक सूची के साथ एक सेट संपुटित नहीं,:

new ArrayList(new LinkedHashSet()) 

यह जो संग्रह ;-)

+2

यह कन्स्ट्रक्टर इसे सेट करने की बजाय नई सूची में सेट की सामग्री की प्रतिलिपि बनाता है। – Calum

+0

@ कॉलम, यह सही है, लेकिन किसी सूची में डुप्लीकेट जोड़ने के बारे में चिंता करने की बजाय, वह अपनी ऑब्जेक्ट्स को सेट में जोड़ सकता है (और सेट को डुप्लिकेट को फ़िल्टर करने के बारे में चिंता करने दें) और बस इसे सहेजते समय सूची में सेट करें बाहरी विधि के लिए। –

+3

यह एक सूची में एक सेट कॉपी करता है लेकिन आपके पास कोई प्रसिद्ध ऑर्डरिंग नहीं है। लेकिन यह सवाल क्या है। – Janning

0

documentation for collection interfaces के एक असली मालिक है किसी के लिए अन्य कार्यान्वयन के पत्तों का कहना है:

सेट - एक संग्रह जिसमें डुप्लिकेट तत्व नहीं हो सकते हैं।
सूची - एक आदेश दिया गया संग्रह (कभी-कभी अनुक्रम कहा जाता है)। सूची में डुप्लिकेट तत्व हो सकते हैं।

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

+0

मैंने विशेष रूप से उल्लेख किया है कि मुझे एक सूची कार्यान्वयन की आवश्यकता है। मेरा विश्वास करो, एक कारण है। – Yuval

+0

क्या कारण है क्योंकि आप एक एपीआई के साथ बातचीत कर रहे हैं जो एक पैरामीटर के रूप में सूची ले रहा है (संग्रह के बजाए)? –

+0

से निपटने के लिए यह थोड़ा परेशान है असल में एपीआई एक नक्शा <खाता प्रकार, मानचित्र <खाता प्रकार, सूची >> लेता है, जिसका मतलब है कि दर्जनों से सैकड़ों सूचियों के आसपास कहीं भी हो रहा है ... बाह। – Yuval

0

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

+0

मैं इस विचार पर वापस आने के लिए तैयार था (जो अंततः मुझे करना था) अगर कोई भी बेहतर कुछ सुझाव नहीं देता = 8-) ऊपर अपना जवाब देखें। – Yuval

11

तो आखिरकार मैंने यही किया। मैं उम्मीद करता हूं कि इससे किसी की मदद होगी।

class NoDuplicatesList<E> extends LinkedList<E> { 
    @Override 
    public boolean add(E e) { 
     if (this.contains(e)) { 
      return false; 
     } 
     else { 
      return super.add(e); 
     } 
    } 

    @Override 
    public boolean addAll(Collection<? extends E> collection) { 
     Collection<E> copy = new LinkedList<E>(collection); 
     copy.removeAll(this); 
     return super.addAll(copy); 
    } 

    @Override 
    public boolean addAll(int index, Collection<? extends E> collection) { 
     Collection<E> copy = new LinkedList<E>(collection); 
     copy.removeAll(this); 
     return super.addAll(index, copy); 
    } 

    @Override 
    public void add(int index, E element) { 
     if (this.contains(element)) { 
      return; 
     } 
     else { 
      super.add(index, element); 
     } 
    } 
} 
+8

सावधान रहें - LinkedList.contains() को सूची में कोई ऑब्जेक्ट निहित करने के लिए पूरी सूची स्कैन करने की आवश्यकता है। इसका अर्थ यह है कि जब आप बड़ी सूची में ऑब्जेक्ट जोड़ रहे होते हैं, तो संपूर्ण सूची प्रत्येक ऐड ऑपरेशन (सबसे खराब मामले में) के लिए स्कैन की जाती है। यह धीमा होने का अंत हो सकता है। –

+7

इसके अलावा, आपका ऐडअल ओवरराइड addAll() पर संग्रहीत संग्रह में डुप्लिकेट की जांच नहीं करता है। –

5

आप गंभीरता से की dhiller जवाब पर विचार करना चाहिए:, इसके बजाय

  1. डुप्लिकेट कम लिस्ट में अपने वस्तुओं को जोड़ने के बारे में चिंता करने की, एक सेट (किसी भी कार्यान्वयन) में शामिल करें जो कि प्रकृति फिल्टर बाहर से डुप्लीकेट्स
  2. जब आपको उस विधि को कॉल करने की आवश्यकता होती है जिसके लिए एक सूची की आवश्यकता होती है, तो इसे new ArrayList(set) (या new LinkedList(set), जो भी हो) में लपेटें।

मुझे लगता है कि समाधान आप NoDuplicatesList साथ तैनात ज्यादातर विधि के साथ, कुछ मुद्दे हैं, साथ ही आपके वर्ग संग्रह में डुप्लिकेट अपने addAll() विधि को पास किए जाने के लिए जाँच संभाल नहीं करता है।

+0

मुझे इन() मुद्दों के बारे में जानना अच्छा लगेगा। AddAll() के लिए, मैं दिए गए संग्रह की एक प्रति बना देता हूं और पहले से ही 'इस' में सभी ऑब्जेक्ट्स को हटा देता हूं। यह डुप्लीकेट को कैसे संभाल नहीं करता है? – Yuval

+0

जैसा कि मैंने आपकी कक्षा पोस्टिंग पर अपनी टिप्पणी में उल्लेख किया है, इसमें() को सूची में निहित है या नहीं, यह पता लगाने के लिए() सबसे खराब स्थिति में) को स्कैन करना है। यदि आपके पास 1 मिलियन आइटम की सूची है और इसे 10 अलग-अलग जोड़ें, तो (सबसे खराब मामले में) दस मिलियन से अधिक आइटम स्कैन किए गए हैं। –

+0

addAll() के लिए, यदि संग्रह को पास करने के लिए पास किया गया संग्रह में डुप्लीकेट स्वयं होते हैं, तो वे नहीं पता चला है। उदाहरण के लिए: आपकी सूची {ए, बी, सी, डी} पैरामीटर सूची {बी, डी, ई, ई, ई}। आप पैरामीटर की एक प्रति बनाते हैं, और हटाने के बाद इसमें सभी {ई, ई, ई} होते हैं। –

2

मुझे ऐसा कुछ चाहिए, इसलिए मैं कॉमन्स संग्रह में गया और सेटयूनिकलिस्ट का उपयोग किया, लेकिन जब मैंने कुछ प्रदर्शन परीक्षण चलाया, तो मैंने पाया कि अगर मैं सेट का उपयोग करना चाहता हूं और प्राप्त करना चाहता हूं तो यह मामले की तुलना में अनुकूल नहीं लगता है Set.toArray() विधि का उपयोग करके एक ऐरे, SetUniqueTest ने भरने के लिए 20: 1 समय लिया और फिर अन्य कार्यान्वयन की तुलना में 100,000 स्ट्रिंग्स को पार किया, जो एक बड़ा सौदा अंतर है, इसलिए यदि आप प्रदर्शन के बारे में चिंता करते हैं, तो मैं आपको सलाह देता हूं सेट का उपयोग करें और SetUniqueList उपयोग करने के बजाय एक सरणी मिलता है, जब तक आप वास्तव में, SetUniqueList के तर्क की जरूरत है तो आप अन्य समाधान की जाँच करने की आवश्यकता है ...

परीक्षण कोड मुख्य विधि:

public static void (String [] args) {

SetUniqueList pq = SetUniqueList.decorate(new ArrayList()); 
Set s = new TreeSet(); 

long t1 = 0L; 
long t2 = 0L; 
String t; 


t1 = System.nanoTime(); 
for (int i = 0; i < 200000; i++) { 
    pq.add("a" + Math.random()); 
} 
while (!pq.isEmpty()) { 
    t = (String) pq.remove(0); 
} 
t1 = System.nanoTime() - t1; 

t2 = System.nanoTime(); 
for (int i = 0; i < 200000; i++) { 
    s.add("a" + Math.random()); 
} 

s.clear(); 
String[] d = (String[]) s.toArray(new String[0]); 
s.clear(); 
for (int i = 0; i < d.length; i++) { 
    t = d[i]; 

} 
t2 = System.nanoTime() - t2; 

System.out.println((double)t1/1000/1000/1000); //seconds 
System.out.println((double)t2/1000/1000/1000); //seconds 
System.out.println(((double) t1)/t2);  //comparing results 

}

सादर मोहम्मद स्लीम http://abusleem.net/blog

-3

मैं सिर्फ इस तरह अपने खुद के छोटे से पुस्तकालय में अपने ही UniqueList बनाया:

package com.bprog.collections;//my own little set of useful utilities and classes 

import java.util.HashSet; 
import java.util.ArrayList; 
import java.util.List; 
/** 
* 
* @author Jonathan 
*/ 
public class UniqueList { 

private HashSet masterSet = new HashSet(); 
private ArrayList growableUniques; 
private Object[] returnable; 

public UniqueList() { 
    growableUniques = new ArrayList(); 
} 

public UniqueList(int size) { 
    growableUniques = new ArrayList(size); 
} 

public void add(Object thing) { 
    if (!masterSet.contains(thing)) { 
     masterSet.add(thing); 
     growableUniques.add(thing); 
    } 
} 

/** 
* Casts to an ArrayList of unique values 
* @return 
*/ 
public List getList(){ 
    return growableUniques; 
} 

public Object get(int index) { 
    return growableUniques.get(index); 
} 

public Object[] toObjectArray() { 
    int size = growableUniques.size(); 
    returnable = new Object[size]; 
    for (int i = 0; i < size; i++) { 
     returnable[i] = growableUniques.get(i); 
    } 
    return returnable; 
    } 
} 

मेरे पास एक टेस्टकोलेक्शन क्लास है जो इस तरह दिखता है:

package com.bprog.collections; 
import com.bprog.out.Out; 
/** 
* 
* @author Jonathan 
*/ 
public class TestCollections { 
    public static void main(String[] args){ 
     UniqueList ul = new UniqueList(); 
     ul.add("Test"); 
     ul.add("Test"); 
     ul.add("Not a copy"); 
     ul.add("Test"); 
     //should only contain two things 
     Object[] content = ul.toObjectArray(); 
     Out.pl("Array Content",content); 
    } 
} 

ठीक काम करता है। यह सब करता है कि यह एक सेट में जोड़ता है यदि उसके पास पहले से नहीं है और वहां एक ऐरेलिस्ट है जो वापसी योग्य है, साथ ही ऑब्जेक्ट सरणी भी है।

+2

यह सूची – Eva

+0

हाँ लागू नहीं करता है, आपको सूची इंटरफ़ेस को लागू करने के लिए इसमें कुछ और तरीके जोड़ना चाहिए। – gyurix

0

add विधि में, का उपयोग क्यों नहीं करते HashSet.consist() के बजाय डुप्लिकेट की जांच करें। HashSet.add() अन्य डुप्लिकेट और false अन्यथा true वापस करेगा।

+0

'हैशसेट # क्या है() '? – naXa

9

यहां मैंने जो किया और यह काम करता है।

मान लीजिए कि मेरे पास एक नई LinkedHashMap बनाई गई पहली चीज़ के साथ काम करने के लिए ArrayList है।

LinkedHashSet<E> hashSet = new LinkedHashSet<E>() 

फिर मैं अपना नया तत्व LinkedHashSet पर जोड़ने का प्रयास करता हूं। ऐड विधि LinkedHasSet को परिवर्तित नहीं करती है और नया तत्व डुप्लिकेट होने पर गलत लौटाता है। तो यह एक शर्त बन जाती है जिसे मैं ArrayList में जोड़ने से पहले परीक्षण कर सकता हूं।

if (hashSet.add(E)) arrayList.add(E); 

डुप्लिकेट को सरणी सूची में जोड़ने से रोकने के लिए यह एक आसान और सुरुचिपूर्ण तरीका है। यदि आप चाहते हैं कि आप ArrayList को विस्तारित करने वाली कक्षा में ऐड विधि के अंदर और ओवरराइड कर सकें। तत्वों के माध्यम से लूप करके और ऐड विधि को कॉल करके addAll से निपटने के लिए बस याद रखें।

+1

हाँ, मुझे लगता है, यह इसके लिए सबसे अच्छा समाधान है, आप एक सामान्य हैशसेट का उपयोग भी कर सकते हैं, लिंक नहीं, और फिर आप अपनी सूची का उपयोग अपनी इच्छानुसार कर सकते हैं, आप यह भी तय कर सकते हैं कि कुछ स्थितियों में क्या करना है, जैसे एक विशिष्ट इंडेक्स से पहले एक सूची के अंदर एक तत्व जोड़ने में, आप यह तय कर सकते हैं कि आप डुप्लीकेट आइटम को इस स्थिति में ले जाना चाहते हैं या नहीं। – gyurix

+0

यहां सबसे अच्छा समाधान ...मेरे अनन्य लिस्ट क्लास कोड – marcolopes

+0

पोस्ट करेंगे यह मेरे बीएफएस ग्राफ एल्गोरिदम में मेरे लिए काम करता है। क्योंकि मेरे पास कुछ नोड्स थे जिन्हें मैंने कतार (लिंक्डलिस्ट) में जोड़ा था, अगर वे पहले से नहीं थे। –

0

नोट: यह उपसूची खाते में कार्यान्वयन नहीं करता है।

import java.util.ArrayList; 
import java.util.Collection; 
import java.util.HashSet; 
import java.util.Set; 

public class UniqueList<T> extends ArrayList<T> { 

    private static final long serialVersionUID = 1L; 

    /** Unique elements SET */ 
    private final Set<T> set=new HashSet(); 

    /** Used by addAll methods */ 
    private Collection<T> addUnique(Collection<? extends T> col) { 
     Collection<T> unique=new ArrayList(); 
     for(T e: col){ 
      if (set.add(e)) unique.add(e); 
     } 
     return unique; 
    } 

    @Override 
    public boolean add(T e) { 
     return set.add(e) ? super.add(e) : false; 
    } 

    @Override 
    public boolean addAll(Collection<? extends T> col) { 
     return super.addAll(addUnique(col)); 
    } 

    @Override 
    public void add(int index, T e) { 
     if (set.add(e)) super.add(index, e); 
    } 

    @Override 
    public boolean addAll(int index, Collection<? extends T> col) { 
     return super.addAll(index, addUnique(col)); 
    } 

}