संग्रह .emptyList () बनाम नई आवृत्ति


241

व्यवहार में, क्या खाली सूची को वापस करना बेहतर है इस :

return Collections.emptyList();

या इस तरह :

return new ArrayList<Foo>();

या यह पूरी तरह से निर्भर है कि आप लौटी हुई सूची के साथ क्या करने जा रहे हैं?

जवाबों:


300

मुख्य अंतर यह है कि Collections.emptyList()एक अपरिवर्तनीय सूची, यानी एक सूची, जिसमें आप तत्व नहीं जोड़ सकते हैं, लौटाता है । (वही List.of()जावा 9 में पेश किया गया है)

दुर्लभ मामलों में जहां आप लौटी हुई सूची को संशोधित करना चाहते हैं , Collections.emptyList()और List.of()इस प्रकार यह एक अच्छा विकल्प नहीं है।

मैं कहूंगा कि एक अपरिवर्तनीय सूची वापस करना पूरी तरह से ठीक है (और यहां तक ​​कि पसंदीदा तरीका) जब तक कि अनुबंध (प्रलेखन) स्पष्ट रूप से अलग तरह से राज्य नहीं करता है।


इसके अलावा, emptyList() प्रत्येक कॉल के साथ एक नई वस्तु नहीं बना सकता है।

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

इस emptyListप्रकार लग रहा है के कार्यान्वयन :

public static final <T> List<T> emptyList() {
    return (List<T>) EMPTY_LIST;
}

इसलिए यदि आपकी विधि (जो एक खाली सूची लौटाती है) को बहुत बार कहा जाता है, तो यह दृष्टिकोण आपको सीपीयू और मेमोरी वार दोनों से थोड़ा बेहतर प्रदर्शन दे सकता है।


4
तो, Collections.emptyList()आइए हम कहते हैं, त्रुटि जाँच और इस तरह के लिए अधिक उपयुक्त होगा ?
MRE

1
API क्लाइंट नहीं मिलेगा NullPointerExceptionवापस लौट कर Collections.emptyList()के बजाय null
RealPK

@PK_J एक महत्वपूर्ण बिंदु बनाता है। Collections.emptyList()पुनरावृत्त है और एक लंबाई लौटाता है, इसलिए इसे बिना किसी अपवाद के फेंके गए छोरों के लिए इस्तेमाल किया जा सकता है।
ndm13

का उपयोग करने के बारे में क्या List.of()?

4
@AJW, हाँ। लेकिन कहने की तुलना में, new ArrayList<>()यह डिजाइन निर्णय को भी स्पष्ट करता है; तत्वों को इस सूची में नहीं जोड़ा जाएगा।
23/19

51

जावा 5.0 से शुरू होकर आप कंटेनर में तत्व के प्रकार को निर्दिष्ट कर सकते हैं:

Collections.<Foo>emptyList()

मैं अन्य प्रतिक्रियाओं से सहमत हूं कि उन मामलों के लिए जहां आप खाली सूची वापस करना चाहते हैं, जो खाली रहती हैं, आपको इस दृष्टिकोण का उपयोग करना चाहिए।


38
जावा 7 से शुरू करते हुए, आप संकलक को लक्ष्य प्रकार से जेनेरिक पद्धति के आह्वान के प्रकार का अनुमान लगा सकते हैं:List<Foo> list = Collections.emptyList()
पॉल जैक्सन

28

Collections.emptyList अपरिवर्तनीय है, इसलिए दो संस्करणों के बीच अंतर है इसलिए आपको लौटाए गए मूल्य के उपयोगकर्ताओं पर विचार करना होगा।

लौटना new ArrayList<Foo>हमेशा ऑब्जेक्ट का एक नया उदाहरण बनाता है, इसलिए इसके साथ बहुत कम अतिरिक्त लागत जुड़ी होती है जो आपको उपयोग करने का कारण दे सकती है Collections.emptyList। मुझे emptyListसिर्फ इसलिए उपयोग करना पसंद है क्योंकि यह अधिक पठनीय है।


14

हालांकि सावधानी से रहें। यदि आप वापस लौटते हैं Collections.emptyList()और फिर इसके साथ कुछ बदलाव करने की कोशिश करते हैं add(), जैसे कि sm, तो, UnsupportedOperationException()क्योंकि u में Collections.emptyList()एक अपरिवर्तनीय वस्तु होगी।


7

मैं के साथ जाना होगा Collections.emptyList()अगर लौटे सूची (के रूप में सूची अपरिवर्तनीय है) किसी भी तरह से संशोधित नहीं किया जा रहा है, नहीं तो मैं विकल्प 2 के साथ जाना होगा।

इसका लाभ Collections.emptyList()यह है कि प्रत्येक बार एक ही स्टैटिक इंस्टेंस लौटाया जाता है और इसलिए प्रत्येक कॉल के लिए इंस्टेंस क्रिएट नहीं होता है।


3

संग्रह का उपयोग करें। खाली सूची () यदि आप यह सुनिश्चित करना चाहते हैं कि लौटी हुई सूची कभी संशोधित न हो। यह वही है जिसे कॉल करने पर लौटाया जाता है ():

/**
 * The empty list (immutable). 
 */
public static final List EMPTY_LIST = new EmptyList();

मैं यहां यह पता लगाने की कोशिश कर रहा Collections.emptyList()था कि क्या कॉलिंग की निर्माण लागत थी। कार्यान्वयन विवरण देखकर (हालांकि सभी JVM पर समान नहीं है) पुष्टि करें कि यह नहीं है। @ अतुल, यह किस जेवीएम से है?
wjl

2

दिए गए उत्तर इस तथ्य पर बल देते हैं कि emptyList()एक अपरिवर्तनीय रिटर्न देता है Listलेकिन विकल्प नहीं देते हैं। कंस्ट्रक्टर के ArrayList(int initialCapacity)विशेष मामले 0इसलिए new ArrayList<>(0)बदले new ArrayList<>()जा सकते हैं वह भी एक व्यवहार्य समाधान हो सकता है:

/**
 * Shared empty array instance used for empty instances.
 */
private static final Object[] EMPTY_ELEMENTDATA = {};

[...]

/**
 * Constructs an empty list with the specified initial capacity.
 *
 * @param  initialCapacity  the initial capacity of the list
 * @throws IllegalArgumentException if the specified initial capacity
 *         is negative
 */
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

(जावा 1.8.0_72 से स्रोत)


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

1
जैसा कि मैंने अपने शब्दों के साथ जोर देने की कोशिश की ( व्यवहार्य हो सकती है ): यह सब आपके उपयोग के मामले पर निर्भर करता है। मैं आम तौर पर या तो उत्परिवर्तित या अयोग्य संग्रह लौटाता हूं, न कि वेदर के आधार पर मिश्रण जो वे खाली हैं या नहीं। और "बहुत धीमे दावे" का मुकाबला करने के लिए: यह वर्तमान कार्यान्वयन है।
रेना

ओह यार, जद के 2 प्रमुख संस्करणों का हवाला देते हुए मुझे देखो। इसलिए java8 0. के प्रारंभिक आकार से डिफ़ॉल्ट क्षमता तक पूरी तरह से कूदकर अड़चन से बचा जाता है। क्षमा करें, मैं बहुत गलत था।
पैट्रिक एम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.