List.of और Arrays.asList में क्या अंतर है?


117

जावा 9 ने सूचियों के लिए नए कारखाने के तरीके पेश किए List.of:

List<String> strings = List.of("first", "second");

पिछले और नए विकल्प में क्या अंतर है? यही है, इस बीच क्या अंतर है:

Arrays.asList(1, 2, 3);

और इस:

List.of(1, 2, 3);

1
स्टुअर्ट "बीकर" मार्क्स द्वारा यह बात भी देखें ।
user1803551

20
@ user1803551 हालांकि मैं आपकी हताशा को समझता हूं, यह तर्क वास्तव में अवांछित मिसाल कायम कर सकता है। यहाँ बहुत सारे सवालों का जवाब है जो 'स्पष्ट रूप से कहा गया है' (यह कैसे परिभाषित करता है) पर निर्भर करता है। मैं आपसे इस चर्चा को मेटा में लाने का आग्रह करूंगा लेकिन मुझे पूरा यकीन है कि इस तरह की चर्चा पहले से ही मौजूद होनी चाहिए (और मैं उम्मीद कर रहा हूं कि कोई इसे ढूंढ सकता है और इसे लिंक कर सकता है :-)
दिमित्री फासरकिस हिलियार्ड

4
@ user1803551 Javadocs इन दो तरीकों (जैसे अंतरिक्ष की खपत या प्रदर्शन) के कार्यान्वयन विवरण के बीच अंतर का उल्लेख नहीं करता है। मुझे लगता है कि लोग इन विवरणों को भी जानना चाहेंगे।
क्क्काजलोव

5
@ZhekaKozlov स्वीकार किए जाते हैं और सुपर उत्कीर्ण जवाब या तो नहीं है। यह आपको स्वीकृत मानकों के बारे में क्या बताता है? यहां तक कि डॉक्स (क्रमांकन, पहचान, आदेश) की तुलना में इसकी कम जानकारी है। यदि कुछ भी हो, तो उस जानकारी को जोड़ने के लिए OpenJDK से अनुरोध करें।
user1803551

3
इस सवाल पर मेटा पर चर्चा की जा रही है ।
दिमित्रिस फासारकिस हिलियार्ड

जवाबों:


172

Arrays.asListएक परस्पर सूची लौटाता है जबकि सूची द्वारा लौटाया जाता List.ofहै अपरिवर्तनीय है :

List<Integer> list = Arrays.asList(1, 2, null);
list.set(1, 10); // OK

List<Integer> list = List.of(1, 2, 3);
list.set(1, 10); // Fails with UnsupportedOperationException

Arrays.asListशून्य तत्वों को अनुमति List.ofनहीं देता है:

List<Integer> list = Arrays.asList(1, 2, null); // OK
List<Integer> list = List.of(1, 2, null); // Fails with NullPointerException

contains नल के साथ अलग व्यवहार करता है:

List<Integer> list = Arrays.asList(1, 2, 3);
list.contains(null); // Returns false

List<Integer> list = List.of(1, 2, 3);
list.contains(null); // Fails with NullPointerException

Arrays.asListपारित सरणी का एक दृश्य लौटाता है, इसलिए सरणी में परिवर्तन सूची में भी दिखाई देगा। के लिए List.ofयह सच नहीं है:

Integer[] array = {1,2,3};
List<Integer> list = Arrays.asList(array);
array[1] = 10;
System.out.println(list); // Prints [1, 10, 3]

Integer[] array = {1,2,3};
List<Integer> list = List.of(array);
array[1] = 10;
System.out.println(list); // Prints [1, 2, 3]

22
एक सूची के लिए अलग तरह से व्यवहार करने के आधार पर इसका निर्माण कैसे किया जाता है, यह मेरे लिए बहुत वस्तु उन्मुख नहीं लगता है। हो सकता है कि अगर List.of ने एक ImmutableList प्रकार लौटा दिया, तो इसका मतलब होगा। यह यहाँ एक बहुत ही लकीर का फकीर है।
सैंडी चैपमैन

5
मैं जावा डेवलपर नहीं हूं, इसलिए इसे एक आकस्मिक अवलोकन के रूप में लें। व्यवहार के भिन्न होने का संभवतः एक अच्छा कारण है, लेकिन अगर मेरे पास सूची की तरह एक सूची <Integer> लौटाने की विधि थी, तो इंटरफ़ेस मेरे लिए यह जानने के लिए पर्याप्त नहीं होगा कि क्या मैं एक रनटाइम अपवाद प्राप्त करूँगा यदि मैं इसे जाँचूं नल के लिए। इसी तरह, उस तरीके के कार्यान्वयन में बदलाव मेरी पद्धति की कॉल साइट से कोड दूर को प्रभावित कर सकता है अगर वह जाँच कहीं और होती है। @ निकोलाई
सैंडी चैपमैन

8
@ कैंडीचंपमैन कुछ (या अधिकांश?) के लिए अप्रत्याशित व्यवहार हो सकता है, लेकिन यह दस्तावेज व्यवहार है। के List.contains(Object o)javadoc से : "फेंकता है [...] NullPointerException - यदि निर्दिष्ट तत्व शून्य है और यह सूची शून्य तत्वों (वैकल्पिक) की अनुमति नहीं देती है"। या इंटरफ़ेस के लेन-देन परिचय से जो कुछ पढ़ता है: "कुछ संग्रह कार्यान्वयन में उन तत्वों पर प्रतिबंध है जो उनके पास हो सकते हैं"
हारून

11
@ एरन कम से कम यह एक अच्छी तरह से प्रलेखित टपका हुआ अमूर्त है :)
सैंडी चैपमैन

6
@ कैंडी चैपमैन: किसी प्रकार की वापसी List.of करता हैImmutableList , इसका वास्तविक नाम सिर्फ गैर-सार्वजनिक कार्यान्वयन विवरण है। यदि यह सार्वजनिक था और किसी ने इसे Listफिर से डाला , तो अंतर कहां था? ऐसा अंतर कहां है Arrays.asList, जो गैर-सार्वजनिक Listकार्यान्वयन लौटाता है, जो प्रयास करते समय addया remove, या उस सूची को छोड़ Collections.unmodifiableListदेता है, जिसके द्वारा वापस लौटा जाता है, जिसमें कोई संशोधन नहीं होता है? यह Listइंटरफ़ेस में निर्दिष्ट अनुबंधों के बारे में है। संग्रह वैकल्पिक तरीकों के साथ इंटरफेस हमेशा OOP जावा 1.2 के बाद से थे ...
Holger

31

Arrays.asListऔर के बीच का अंतरList.of

JavaDocs देखें और स्टुअर्ट मार्क्स (या इसके पिछले संस्करण) द्वारा यह बात करें ।

मैं कोड उदाहरण के लिए निम्नलिखित का उपयोग करूंगा:

List<Integer> listOf = List.of(...);
List<Integer> asList = Arrays.asList(...);
List<Integer> unmodif = Collections.unmodifiableList(asList);

संरचनात्मक अपरिवर्तनीयता (या: असमानता)

संरचनात्मक रूप से बदलने के किसी भी प्रयास का List.ofपरिणाम होगा UnsupportedOperationException। इसमें ऐड , सेट और रिमूव जैसे ऑपरेशन शामिल हैं । हालाँकि, आप सूची में ऑब्जेक्ट्स की सामग्री को बदल सकते हैं (यदि ऑब्जेक्ट अपरिवर्तनीय नहीं हैं), तो सूची "पूरी तरह से अपरिवर्तनीय" नहीं है।

के साथ बनाई गई unmodifiable सूचियों के लिए यह वही भाग्य है Collections.unmodifiableList। केवल यह सूची मूल सूची का एक दृश्य है, इसलिए यदि आप मूल सूची को बदलते हैं तो यह बदल सकती है।

Arrays.asListपूरी तरह से अपरिवर्तनीय नहीं है, इसमें कोई प्रतिबंध नहीं है set

listOf.set(1, "a");  // UnsupportedOperationException
unmodif.set(1, "a"); // UnsupportedOperationException
asList.set(1, "a");  // modified unmodif! unmodif is not truly unmodifiable

इसी तरह, बैकिंग ऐरे (यदि आप इसे पकड़ते हैं) को बदलने से लिस्ट बदल जाएगी।

संरचनात्मक अपरिहार्यता रक्षात्मक कोडिंग, संगामिति और सुरक्षा से संबंधित कई दुष्प्रभावों के साथ आती है जो इस उत्तर के दायरे से परे हैं।

अशक्त शत्रुता

List.ofऔर जावा 1.5 के बाद से कोई भी संग्रह nullएक तत्व के रूप में अनुमति नहीं देता है । nullएक तत्व या यहां तक ​​कि एक लुकअप के रूप में पारित करने का प्रयास करने के परिणामस्वरूप होगा NullPointerException

चूंकि Arrays.asList1.2 (संग्रह रूपरेखा) से एक संग्रह है, यह nullएस की अनुमति देता है ।

listOf.contains(null);  // NullPointerException
unmodif.contains(null); // allowed
asList.contains(null);  // allowed

क्रमबद्ध रूप

चूंकि List.ofजावा 9 में पेश किया गया है और इस पद्धति द्वारा बनाई गई सूचियों का अपना (द्विआधारी) क्रमबद्ध रूप है, वे पहले के जेडीके संस्करणों (कोई बाइनरी संगतता ) पर deserialized नहीं किया जा सकता है । हालांकि, आप उदाहरण के लिए, JSON के साथ डी / सीरियल कर सकते हैं।

पहचान

Arrays.asListआंतरिक रूप से कॉल करता है new ArrayList, जो संदर्भ असमानता की गारंटी देता है।

List.ofआंतरिक कार्यान्वयन पर निर्भर करता है। लौटे उदाहरणों में संदर्भ समानता हो सकती है, लेकिन चूंकि यह गारंटी नहीं है कि आप इस पर भरोसा नहीं कर सकते।

asList1 == asList2; // false
listOf1 == listOf2; // true or false

यह उल्लेख करते हुए कि सूचियाँ समान हैं (थ्रू List.equals) यदि उनमें समान तत्व समान क्रम में हैं, तो इस बात की परवाह किए बिना कि वे कैसे बनाए गए थे या वे कौन से संचालन समर्थन करते हैं।

asList.equals(listOf); // true i.f.f. same elements in same order

कार्यान्वयन (चेतावनी: विवरण संस्करणों पर बदल सकते हैं)

यदि सूची में तत्वों की संख्या List.of2 या उससे कम है, तो तत्वों को एक विशेष (आंतरिक) वर्ग के क्षेत्रों में संग्रहीत किया जाता है। एक उदाहरण वह सूची है जो 2 तत्वों (आंशिक स्रोत) को संग्रहीत करती है:

static final class List2<E> extends AbstractImmutableList<E> {
    private final E e0;
    private final E e1;

    List2(E e0, E e1) {
        this.e0 = Objects.requireNonNull(e0);
        this.e1 = Objects.requireNonNull(e1);
    }
}

अन्यथा वे एक समान रूप में एक सरणी में संग्रहीत होते हैं Arrays.asList

समय और अंतरिक्ष दक्षता

List.ofकार्यान्वयन करना, जिससे क्षेत्र के आधार पर (आकार <2) कर रहे हैं थोड़ा तेजी से कुछ कार्यों पर प्रदर्शन करते हैं। उदाहरण के लिए, size()सरणी लंबाई को लाए बिना एक स्थिरांक लौटा सकता है, और contains(E e)इसे ओवरहेड ओवरहेड की आवश्यकता नहीं होती है।

के माध्यम से एक unmodifiable सूची का निर्माण List.ofभी तेज है। उपर्युक्त कंस्ट्रक्टर की तुलना 2 संदर्भ असाइनमेंट (और तत्वों की मनमानी राशि के लिए भी) से करें

Collections.unmodifiableList(Arrays.asList(...));

जो 2 सूचियों और अन्य उपरि बनाता है। अंतरिक्ष के संदर्भ में, आप UnmodifiableListरैपर के साथ-साथ कुछ पेनी भी बचाते हैं । अंततः, HashSetसमकक्ष में बचत अधिक ठोस होती है।


निष्कर्ष समय: उपयोग करें List.ofजब आप एक सूची चाहते हैं जो नहीं बदलती है और Arrays.asListजब आप एक सूची चाहते हैं जो बदल सकती है (जैसा कि ऊपर दिखाया गया है)।


1
यह उत्तर मौजूद लोगों के लिए क्यों है, यह देखें ।
14:

3
Arrays.asListपूरी तरह से परस्पर नहीं है। asList.add(1);फेंकता है UnsupportedOperationException
मानचित्रकार

"नल शत्रुतापूर्ण" इसे डालने का एक शानदार तरीका है। मैं बहुत ज्यादा List.ofकिसी भी समय उपयोग नहीं कर सकता लोगों को कॉल करने के लिए containsऔर NullPointerException द्वारा आश्चर्यचकित नहीं होना चाहिए।
नौमेनन

14

List.of और Arrays.asList के बीच अंतर को संक्षेप में बताएं

  1. List.ofडेटा सेट कम और अपरिवर्तित होने पर सबसे अच्छा उपयोग किया जा सकता है, जबकि Arrays.asListबड़े और गतिशील डेटा सेट के मामले में सबसे अच्छा उपयोग किया जा सकता है।

  2. List.ofबहुत कम ओवरहेड स्थान लें क्योंकि इसका क्षेत्र-आधारित कार्यान्वयन है और कम हीप स्थान का उपभोग करता है, दोनों फिक्स्ड ओवरहेड के संदर्भ में और प्रति-तत्व आधार पर। Arrays.asListअधिक ओवरहेड स्पेस लेते समय क्योंकि आरंभीकरण के दौरान यह ढेर में अधिक ऑब्जेक्ट बनाता है।

  3. संग्रह द्वारा लौटाया गया List.ofअपरिवर्तनीय है और इसलिए थ्रेड-सेफ जबकि संग्रह द्वारा लौटाया जाने योग्य Arrays.asListहै और थ्रेड सुरक्षित नहीं है। (अपरिवर्तनीय संग्रह उदाहरण आम तौर पर अपने उत्परिवर्तनीय समकक्षों की तुलना में बहुत कम मेमोरी का उपभोग करते हैं।)

  4. List.ofशून्य तत्वों की अनुमति नहीं देता है जबकि अशक्त तत्वों की Arrays.asListअनुमति देता है।


2
"अपरिवर्तनीय संग्रह उदाहरण आम तौर पर अपने उत्परिवर्तनीय समकक्षों की तुलना में बहुत कम मेमोरी का उपभोग करते हैं।" - वास्तव में? क्या आप उस पर थोड़ा विस्तार से ध्यान देंगे - क्या आपका मतलब यह है कि उन्हें सुरक्षित रूप से साझा किया जा सकता है, या क्या आप इसका मतलब है कि उदाहरण के लिए खुद को किसी भी तरह से अधिक कुशलता से लागू किया जा सकता है?
हल्क

1
@ हेलक अंतरिक्ष दक्षता के बारे में उत्तरदाता सही है। स्टुअर्ट मार्क्स की बात देखें: youtu.be/q6zF3vf114M?t=49m48s
ZhekaKozlov

2
@ZhekaKozlov यह सामान्य रूप से सही प्रतीत होता है, लेकिन मैं बहुत संदेहवादी हूं कि यह Arrays.asListबनाम के बारे में बात करते समय सच है List.of, यह देखते हुए कि पूर्व में सचमुच एक सरणी के चारों ओर सिर्फ एक आवरण है। कम से कम OpenJDK के कार्यान्वयन में बहुत छोटे ओवरहेड दिखाई देते हैं। वास्तव में, List.ofपारित किसी भी सरणी की प्रतियां बनाने की आवश्यकता होगी, इसलिए जब तक कि सरणी खुद को जल्द ही GC'd नहीं जा रही है, ऐसा लगता है कि List.ofइसमें एक बड़ी मेमोरी फ़ुटप्रिंट है।
क्रिस हेस

4
@ChrisHayes कम से कम List.of(x)और List.of(x, y)अधिक कुशल हैं क्योंकि वे सरणियों को आवंटित नहीं करते हैं
ZhekaKozlov

2
@ हेल: यह मत भूलो कि List.ofहर बार नई सूचियों को वापस करने के लिए तरीकों की आवश्यकता नहीं होती है। इन सूचियों की एक अनिर्दिष्ट पहचान है, इसलिए जेवीसी स्तर पर संभाला जा सकता है। यदि इस संस्करण में नहीं है, तो शायद अगले में। यह अनुबंध द्वारा अनुमत है। इसके विपरीत, Array.asListआप जिस ऐरे से गुजर रहे हैं, उसकी पहचान पर निर्भर करता है, क्योंकि परिणामस्वरूप सूची एरे पर देखने योग्य है, जो सभी को अप्रत्यक्ष रूप से बदलते हुए दर्शाती है।
होल्गर

3

उपर्युक्त उत्तरों के अलावा कुछ निश्चित कार्य हैं, जिन पर दोनों अलग List::of- Arrays::asListअलग हैं:

+----------------------+---------------+----------+----------------+---------------------+
|      Operations      | SINGLETONLIST | LIST::OF | ARRAYS::ASLIST | JAVA.UTIL.ARRAYLIST |
+----------------------+---------------+----------+----------------+---------------------+
|          add         |             |       |              |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|        addAll        |             |       |              |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|         clear        |             |       |              |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|        remove        |             |       |              |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|       removeAll      |       ❗️       |        |        ❗️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|       retainAll      |       ❗️       |       |        ❗️        |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|      replaceAll      |             |       |        ✔️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|          set         |             |       |        ✔️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|         sort         |       ✔️       |        |        ✔️      |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|  remove on iterator  |             |       |              |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
| set on list-iterator |             |       |        ✔️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
  1. Is का अर्थ है विधि समर्थित है
  2. ❌ का अर्थ है कि इस विधि को कॉल करने पर एक UnsupportedOperationException फेंक दी जाएगी
  3. ❗️ का अर्थ है कि विधि का समर्थन केवल तभी किया जाता है यदि विधि के तर्क उत्परिवर्तन का कारण नहीं बनते हैं, जैसे संग्रह। ) एक UnsupportedOperationException फेंकता है

संग्रह के बारे में अधिक जानकारी :: singletonList Vs. की सूची


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