2009-05-05 2 views
5
में एक सूची Cons'ing

मैं एक java.util.List list है कहो और मैं (विपक्षe और list को जैसे कि, मैं चाहता हूँ) list की शुरुआत करने के लिए एक तत्व e जोड़कर एक नई List बनाना चाहते हैं। उदाहरण के लिए, यदि listजावा

[1,2,3,4] 

और e5 है, तो cons(e,list) हो जाएगा

[5,1,2,3,4] 

यह list और cons(e,list) के तत्वों के लिए ठीक साझा करने के लिए है, लेकिन list संशोधित नहीं किया जाना चाहिए।

cons को लागू करने का सबसे सरल और/या सबसे प्रभावी तरीका क्या है? परिणाम के लिए यह ठीक नहीं है। Google संग्रह लाइब्रेरी का उपयोग करने की अनुमति है।

क्या होगा यदि listcom.google.common.collect.ImmutableList है?

+1

लिस्प के साथ नहीं परिचित हम में से उन लोगों के लिए , क्या विपक्ष है? –

+13

मैंने व्यवहार को परिभाषित किया और एक उदाहरण दिया। आपको और क्या चाहिए? –

उत्तर

2

क्या आप CompositeCollection का उपयोग कर सकते हैं?

public Collection cons(Collection c1, Collection c2) 
{ 
    CompositeCollection cons = new CompositeCollection(); 
    cons.addComposited(c1); 
    cons.addComposited(c2); 
    return cons; 
} 

यह द्वारा किया जाए या नहीं एक पैरामीटर अपरिवर्तनीय है और अभी भी C1 और C2 मूल संग्रह के द्वारा समर्थित है प्रभावित नहीं किया जाएगा।

आप एक List मैं शायद निम्नलिखित करना होगा की जरूरत है:

public List cons(Collection c1, Collection c2) 
{ 
    ArrayList cons = new ArrayList(c1.size() + c2.size()); 
    cons.addAll(c1); 
    cons.addAll(c2); 
    return cons; 
} 
+3

परिणामस्वरूप संग्रह एक सूची है? –

8
public static<T> List<T> cons(List<T> list, T t) { 
    ArrayList<T> result = new ArrayList<T>(list); 
    result.add(0, t); 
    return result; 
} 

टिप्पणियों के जवाब में संपादित: सवाल "के लिए विपक्ष को लागू करने का सबसे सरल और/या सबसे कारगर तरीका पूछा के बाद से , "मैं" सरल "के साथ चला गया। मैं यह जानकर आश्चर्यचकित नहीं होगा कि अधिक कुशल तरीके हैं। सूची से पहले तत्व को रखना एक और मान्य दृष्टिकोण है, और शुरुआत में सही आकार आवंटित करने से शायद प्रदर्शन में सुधार हो सकता है। सभी बुराईयो की जड़ समयपूर्व इष्टतमीकरण है।

+1

क्या कोई जानता है कि यह अभ्यास में कैसे कार्य करता है? जावा एपीआई के अनुसार: 'इस सूची में निर्दिष्ट स्थिति पर निर्दिष्ट तत्व डालें। उस स्थिति में वर्तमान में तत्व को बदलता है (यदि कोई है) और दाईं ओर के किसी भी बाद के तत्व (एक को उनके सूचकांक में जोड़ता है)। 'क्या इसका मतलब यह है कि' सूची 'के तत्व केवल एक बार फिर से सक्रिय होते हैं? – AndreiM

+0

वूप्स। उल्लेख करने के लिए भूल गए कि मैं 'एड (इंटेल इंडेक्स, ऑब्जेक्ट ओ)' विधि – AndreiM

+3

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

7

Clojure उस प्रकार की लिस्प-वाई सामग्री प्रदान करता है। जबकि ज्यादातर लोग भाषा के लिए क्लोजर का उपयोग करने के बारे में सोचते हैं (जैसे मैं करता हूं), क्लोजर लाइब्रेरीज़ सभी वास्तविक जावा कोड हैं, और यदि आप चाहें तो जावा से डेटा संरचनाओं को केवल एक विशेष लाइब्रेरी के रूप में उपयोग कर सकते हैं। इस तरह आपको विपक्ष करने की क्षमता मिल जाएगी और आपको क्लोजर का उपयोग करने की अपरिवर्तनीयता मिलती है। क्लोजर डेटा स्ट्रैक्टर्स समकक्ष जावा प्रकारों को भी लागू करता है।

बस एक अलग दिशा से एक विचार।

+3

एक विचार जिसका समय निश्चित रूप से आ जाएगा। एसटीएम वास्तव में जेवीएम पारिस्थितिकी में क्लोजर का अधिक स्थायी योगदान हो सकता है। – alphazero

2

मैं अपने 2 सेंट फेंकने जा रहा हूं, फिर देखें कि कोई भी और अधिक सुरुचिपूर्ण के साथ आता है या नहीं।

<E> List<E> cons(E e, List<E> list) { 
    List<E> res = Lists.newArrayListWithCapacity(list.size() + 1); 
    res.add(e); 
    res.addAll(list); 
    return res; 
} 

एक ImmutableList के साथ (पता नहीं है कि यह कैसे कुशल है): सामान्य स्थिति में

<E> ImmutableList<E> cons(E e, ImmutableList<E> list) { 
    return ImmutableList.<E>builder() 
         .add(e) 
         .addAll(list) 
         .build(); 
} 
+1

'Lists.newArrayListWithExpectedSize' 'नया ArrayList ' से टाइप करना वास्तव में आसान है? –

+0

मुझे लगता है, यह संभव आकार बदलने के संचालन से बचने के बारे में है। लेकिन आप http://java.sun.com/javase/6/docs/api/java/util/ArrayList.html#ArrayList(int) का उपयोग कर सकते हैं। उपरोक्त कोड, हालांकि, 'अपेक्षित आकार' से निपट रहा है। पता नहीं 'ज्ञात' क्षमता के साथ तत्काल करने के लिए क्या अंतर है। – msi

+0

@mmyers: इस मामले में, नहीं, लेकिन जब भी संभव हो, मेरी सूचियों को तुरंत चालू करने के लिए सूची में स्थिर तरीकों का उपयोग करने के सम्मेलन को बनाए रखा जाता है। यह आमतौर पर एक जीत है। –

2

निश्चित रूप से एक LinkedList के सिर पर एक आइटम डालने के लिए सबसे कारगर तरीका होगा एक सूचि?

बस LinkedList वर्ग है कि जावा

+0

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

+0

आपने सूची कार्यान्वयन निर्दिष्ट नहीं किया है। मैंने कुछ अवसरों पर लिंक्डलिस्ट का उपयोग किया है जहां सृजन की प्रारंभिक लागत कोई मुद्दा नहीं था लेकिन बाद के आवेषण * एक मुद्दे थे। – Fortyrunner

3

के साथ आता है क्योंकि आप cons समारोह का उल्लेख उपयोग करते हैं, मुझे लगता है कि आप cons कोशिकाओं से बना जुड़ा हुआ सूचियों का वैचारिक मॉडल के साथ इस समस्या तक पहुंचने वाले हैं ग्रहण करेगा। विशेष रूप से, मुझे लगता है कि आप प्रत्येक सूची के बारे में सोच रहे हैं जिसमें car (पहला तत्व) और cdr (उपरोक्त सभी तत्व शामिल हैं)।

जावा लिंक्ड सूचियों को java.util.LinkedList के रूप में समर्थन देता है। ये रैखिक ट्रैवर्सल के लिए अच्छे हैं और तत्वों को बहुत कुशलतापूर्वक डाला जा सकता है। ये ऊपर वर्णित लिंक्ड सूचियों के समान हैं।

जावा भी java.util.ArrayList प्रदान करता है। इस प्रकार की सूची यादृच्छिक पहुंच के लिए अच्छी है, लेकिन तत्वों को सम्मिलित करते समय धीमा हो सकता है। वास्तव में, सूची की शुरुआत में तत्व डालने पर वे सबसे धीमे होते हैं। चूंकि ArrayList एस दृश्यों के पीछे सरणी के रूप में कार्यान्वित किए जाते हैं, इसलिए प्रत्येक तत्व को नए तत्व के लिए जगह बनाने के लिए सूची में एक स्थिति आगे की प्रतिलिपि बनाई जानी चाहिए। अब, यदि आपको एक बड़ी सरणी की आवश्यकता होती है, तो ArrayList एक नई सरणी आवंटित करेगा, सभी तत्वों को कॉपी करेगा, और इसी तरह।

(इसलिए यह संभावना अधिक उत्तरार्द्ध के समान है गूगल के ImmutableList, "यादृच्छिक अभिगम" के रूप में उद्धृत किया गया है।)

आप अपने cons विधि का उपयोग करने अक्सर, मैं जुड़ा हुआ सूचियों के साथ यह उपयोग करने की अनुशंसा की योजना है। एक cons ऑपरेशन अनिवार्य रूप से एक सूची की शुरुआत में एक तत्व जोड़ रहा है। यह सरणी जैसे रैखिक संरचनाओं के साथ थोड़ा सा समझ में आता है। मैं इस कारण से सरणी सूचियों का उपयोग करने की सलाह देता हूं: कि वे नौकरी के लिए अवधारणात्मक रूप से गलत हैं।

बहुत picky के लिए: क्योंकि एक नई सूची हर बार cons कहा जाता है लौटा दिया जाता है, नकल होने चाहिए कि क्या सूची एक LinkedList या एक ArrayList है। हालांकि, cons ऑपरेशन का पूरा प्रिंसिपल यह है कि यह एक लिंक्ड सूची पर काम कर रहा है।

public <E> LinkedList<E> cons(E car, List<E> cdr) { 
    LinkedList<E> destination = new LinkedList<E>(cdr); 
    destination.addFirst(car); 
    return destination; 
} 

ध्यान दें कि उपरोक्त कोड ऊपर जवाब पढ़ने के बाद लिखा गया था, इसलिए मैं किसी भी आकस्मिक साहित्यिक चोरी के लिए हमें खेद है। यदि आप इसे देखते हैं तो मुझे बताएं और मैं ठीक से स्वीकार करूंगा।

मान लें कि आप एक LinkedList लौटने से खुश हैं, आप इस उदाहरण में cdr रूप ImmutableList उपयोग कर सकते हैं।

+0

गंतव्य के बजाय गंतव्य.addFirst (कार) का उपयोग करें .add (0, कार)। यह प्रदर्शन में काफी अंतर नहीं करेगा (हालांकि कुछ, हालांकि) लेकिन मुझे लगता है कि यह बहुत स्पष्ट है। –

+0

यह देखने के लिए बहुत बेहतर है - धन्यवाद! मैं java.util देख रहा था। उस स्निपेट लिखते समय लिस्ट इंटरफ़ेस, इसलिए मैंने इसे याद किया। – Wesley

0

यदि आपके पास केवल इटेबल है तो एक और बदलाव।

public static <E> List<E> cons(E e, Iterable<E> iter) { 
    List<E> list = new ArrayList<E>(); 
    list.add(e); 
    for(E e2: iter) list.add(e2); 
    return list; 
} 

public static <E> List<E> cons(Iterable<E>... iters) { 
    List<E> list = new ArrayList<E>(); 
    for(Iterable<E> iter: iters) for(E e1: iter1) list.add(e1); 
    return list; 
} 
4

मेरा मानना ​​है कि इस सवाल का जवाब क्या तुम सच में की तलाश में हैं यह है:

http://functionaljava.googlecode.com/svn/artifacts/2.20/javadoc/fj/data/List.html

विधि भी cons कहा जाता है।

मुझे इस पुस्तकालय के साथ कोई अनुभव नहीं है। बस दूसरे दिन इसके बारे में सुना। मुझे उम्मीद है कि यह अच्छा है!

+0

कार्यात्मक जावा बहुत अच्छा लग रहा है, लेकिन मैं पहले से ही Google संग्रह पर बहुत अधिक भरोसा कर रहा हूं और एक नई लाइब्रेरी निर्भरता के लिए बाजार में नहीं हूं :-( –

+3

ओह ... ड्रिच करें कि Google बकवास। –

4

एक कुशल समाधान आपके स्वयं के सूची कार्यान्वयन, आलसी प्रतिनिधिमंडल बनाने के लिए होगा। अगर अप्रत्याशित है, तो यह बहुत अधिक परेशानी नहीं होगी।यदि फ़ैक्टरी विधि के माध्यम से बनाया गया है, तो आप तर्क सूची को RandomAccess लागू नहीं करते हैं या नहीं, इस पर निर्भर करते हुए आप दो अलग अंतर्निहित कार्यान्वयनों में से एक का उपयोग भी कर सकते हैं।

सबसे सामान्य स्थिति के लिए (इस संकलित करके देखें कि क्या जांच न की हो, कोई विवेक चेक, आदि):

class ConsList<E> extends AbstractList<E> 
{ 
    private final E first; 
    private final List<E> rest; 

    ConsList(E first, List<E> rest) 
    { 
     this.first = first; 
     this.rest = rest; 
    } 

    public int get(int index) 
    { 
     return (index == 0) ? first : rest.get(index - 1); 
    } 

    public int size() 
    { 
     return rest.size() + 1; 
    } 
} 

मुझे यकीन है कि अन्य तरीकों में से कुछ अधिक कुशल बनाया जा सकता है कर रहा हूँ, और क्रमिक मामला इसके बजाय सार सारणी सूची को विस्तारित करके बेहतर सेवा प्रदान की जाएगी।

+0

और पहले क्या होता है आप एक दूसरा विपक्ष करते हैं। – Brian

+0

मुझे कोई समस्या नहीं दिखाई देती है। प्रत्येक विपक्ष एक नई सूची देता है। विपक्ष (ए, विपक्ष (बी, सी)) एक सूची देता है जिसका "पहला" एक है, और जिसका "आराम" है एक सूची जिसका "पहला" बी है और जिसका "आराम" सी है। एक सूची बनाई गई * पूरी तरह से * विपक्ष का उपयोग करके और EMPTY_LIST अनिवार्य रूप से केवल एक लिंक की गई सूची है, लेकिन यह संस्करण किसी भी बिंदु पर किसी भी अन्य कार्यान्वयन पर स्विच कर सकता है, जो उपयोगी है यदि आप बाकी के कार्यान्वयन को नहीं जानते हैं। –

3

यह अच्छी तरह से ज्ञात नहीं है, लेकिन सूर्य जावैक कंपाइलर एपीआई में एक अपरिवर्तनीय सूची कार्यान्वयन है जो append() और prepend() जैसी विधियों का उपयोग करके नई अपरिवर्तनीय सूचियां देता है। इसका इस्तेमाल करने के लिए आपको classpath पर tools.jar की जरूरत है, और यह आयात बयान:

import com.sun.tools.javac.util.List; 

नमूना कोड:

final List<Integer> list = List.of(6, 7); 
System.out.println(list); 

final List<Integer> newList = 
    list.prepend(5)      // this is a new List 
     .prependList(List.of(1, 2, 3, 4)) // and another new List 
     .append(8)      // and another 
     .reverse();      // and yet another 
System.out.println(newList); 

System.out.println(list == newList); 

System.out.println(list.getClass()); 
System.out.println(newList.getClass()); 

आउटपुट:

6,7
8,7,6,5,4,3,2,1
झूठी
वर्ग com.sun.tools.javac.util.List
वर्ग com.sun.tools.javac.util.List

मैं जानता हूँ कि यह एक आंतरिक एपीआई है और उत्पादन में नहीं किया जाना चाहिए, लेकिन यह बहुत मजेदार है (अंततः एक जावा संग्रह जो सही महसूस करता है)।

नोट:Collection और List इंटरफेस (जैसे add()addAll()) से सभी मानक परिवर्तनशील तरीकों, UnsupportedOperationException फेंक जाहिर है।

संदर्भ: