जब मैं किसी सरणी से स्ट्रीमिंग कर रहा हूं, तो मैं पूर्णांकों को तार से क्यों नहीं मैप कर सकता हूं?


92

यह कोड काम करता है (Javadoc में लिया गया है):

List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
String commaSeparatedNumbers = numbers.stream()
    .map(i -> i.toString())
    .collect(Collectors.joining(", "));

इसे संकलित नहीं किया जा सकता है:

int[] numbers = {1, 2, 3, 4};
String commaSeparatedNumbers = Arrays.stream(numbers)
    .map((Integer i) -> i.toString())
    .collect(Collectors.joining(", "));

आईडिया बताता है कि मेरे पास एक "असंगत वापसी प्रकार स्ट्रिंग है जो लंबोदर अभिव्यक्ति में है"।

क्यों ? और इसे कैसे ठीक करें?

जवाबों:


114

Arrays.stream(int[])IntStreama, a नहीं बनाता है Stream<Integer>। तो आपको mapToObjबस के बजाय कॉल करने की आवश्यकता है map, जब मैपिंग एint किसी वस्तु की ।

यह उम्मीद के अनुसार काम करना चाहिए:

String commaSeparatedNumbers = Arrays.stream(numbers)
    .mapToObj(i -> ((Integer) i).toString()) //i is an int, not an Integer
    .collect(Collectors.joining(", "));

जो आप भी लिख सकते हैं:

String commaSeparatedNumbers = Arrays.stream(numbers)
    .mapToObj(Integer::toString)
    .collect(Collectors.joining(", "));

3
बीच क्या अंतर है IntStreamऔर Stream<Integer>?
फ्लोरियन मार्गाइन

8
@FlorianMargaine एक IntStreamआदिम intमूल्यों के लिए एक धारा विशेषज्ञता है । A Stream<Integer>केवल स्ट्रीम होल्ड Integerऑब्जेक्ट है।
एलेक्सिस सी।

2
@FlorianMargaine IntStreamएक धारा या आदिम (ints) है जबकि Steram<Integer>वस्तुओं की एक धारा है। प्रदर्शन कारणों के लिए आदिम धाराओं में विशेष तरीके हैं।
assylias

7
IntStream.mapToObjएक अपेक्षा करता है IntFunction, एक फ़ंक्शन जो एक intमूल्य का उपभोग .mapToObj((Integer i) -> i.toString())करता है , इसलिए  काम नहीं करता है। इसे वैसे भी अनुशंसित नहीं किया जाएगा क्योंकि इसमें एक अनावश्यक रूपांतरण शामिल intहै Integer। इसके विपरीत, .mapToObj(Integer::toString)अच्छी तरह से काम करता है क्योंकि यह staticविधि को बुलाएगा Integer.toString(int)। ध्यान दें कि यह बुला से अलग है .map(Integer::toString)एक पर  Stream<Integer>बाद के रूप में संकलित नहीं होगा, क्योंकि यह अस्पष्ट है।
होल्गर

1
@cic: नहीं, बुला .map(Integer::toString)एक पर Stream<Integer>दोनों के रूप में वास्तव में अस्पष्ट है, .map(i->i.toString())और .map(i->Integer.toString(i))मान्य हैं। लेकिन यह आसानी से उपयोग करने योग्य है .map(Object::toString)
होल्गर

19

Arrays.stream(numbers)IntStreamएक IntStreamआवश्यकता IntUnaryOperator(यानी एक फ़ंक्शन int -> int) पर हुड और नक्शे के संचालन के तहत एक निर्माण बनाता है । आप जिस मैपिंग फ़ंक्शन को लागू करना चाहते हैं, वह इस अनुबंध का सम्मान नहीं करता है और इसलिए संकलन त्रुटि है।

boxed()एक पाने के लिए आपको पहले कॉल करना होगा Stream<Integer>(यह Arrays.asList(...).stream()रिटर्न है)। फिर बस फोन करोmap जैसा आपने पहले स्निपेट में किया था वैसा ।

ध्यान दें कि अगर आप की जरूरत है boxed(), जिसके बाद mapआप शायद उपयोग करना चाहते हैंmapToObj सीधे।

लाभ यह है कि किसी वस्तु को mapToObjप्रत्येक intमूल्य को बॉक्स में रखने की आवश्यकता नहीं होती है Integer; मैपिंग फ़ंक्शन के आधार पर आप निश्चित रूप से लागू होते हैं; इसलिए मैं इस विकल्प के साथ जाऊंगा जो लिखना भी कम है।


5

आप Arrays.stream (int []) का उपयोग करके एक इंटेगर स्ट्रीम बना सकते हैं, जिसे आप mapToObjपसंद कर सकते हैं mapToObj(Integer::toString)

String csn = Arrays.stream(numbers) // your numbers array
.mapToObj(Integer::toString)
.collect(Collectors.joining(", "));

उम्मीद है की यह मदद करेगा..


2

कोई बॉक्सिंग, AFAIK, और ढेर का कोई विस्फोट ढेर में जोड़ा:

public static void main(String[] args) {
    IntStream stream = IntStream.of(1, 2, 3, 4, 5, 6);
    String s = stream.collect(StringBuilder::new, (builder, n) -> builder.append(',').append(n), (x, y) -> x.append(',').append(y)).substring(1);
    System.out.println(s);
}

1

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

int[] numbers = {0, 1, 2, 3}; 
String commaSeparatedNumbers = Arrays.stream(numbers)
    .boxed()
    .map((Integer i) -> Integer.toString((int)i))
    .collect(Collectors.joining(", "));

.Boxed () कॉल आपके इंटस्ट्रीम (आदिम ints की एक स्ट्रीम) को स्ट्रीम (ऑब्जेक्ट्स की एक स्ट्रीम - अर्थात्, पूर्णांक ऑब्जेक्ट्स) में कनवर्ट करता है, जो तब किसी ऑब्जेक्ट की वापसी को स्वीकार करेगा (इस मामले में, एक स्ट्रिंग ऑब्जेक्ट) आपका मेमना। यहां यह प्रदर्शन उद्देश्यों के लिए संख्या का एक स्ट्रिंग प्रतिनिधित्व है, लेकिन यह आसानी से (और अधिक व्यावहारिक रूप से) किसी भी स्ट्रिंग ऑब्जेक्ट हो सकता है - जैसा कि पहले उल्लेख किए गए स्ट्रिंग सरणी के तत्व की तरह है।

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

हैप्पी कोडिंग!


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