जावा स्ट्रीम के साथ पूर्णांकों की सूची कैसे प्राप्त करें?


364

मैं पूर्णांकों की सूची का योग करना चाहता हूं। यह निम्नानुसार काम करता है, लेकिन वाक्यविन्यास सही नहीं लगता है। क्या कोड को अनुकूलित किया जा सकता है?

Map<String, Integer> integers;
integers.values().stream().mapToInt(i -> i).sum();

5
"लेकिन वाक्यविन्यास सही नहीं लगता है" आपको क्या लगता है? यह सामान्य मुहावरा है। हो सकता है कि आप mapToLongउन ओवरफ्लो से बचने के लिए उपयोग करना चाहते हैं , जो आपके मानचित्र के मूल्यों के आधार पर हो सकते हैं।
एलेक्सिस सी।

3
@ जेबीएनज़ेट मुझे i -> iव्यक्तिगत रूप से बहुत स्पष्ट है। ठीक है, हाँ आपको यह जानने की जरूरत है कि मूल्य स्वचालित रूप से अनबॉक्स किया जाएगा, लेकिन यह जावा 5 के बाद से सच है ...
एलेक्सिस सी।

4
@AlexisC। यह समझ में आता है क्योंकि यह mapToInt () में पास हो गया है, और क्योंकि मैं एक अनुभवी डेवलपर हूं। लेकिन i -> i, संदर्भ के बिना, एक noop की तरह दिखता है। पूर्णांक :: intValue अधिक क्रिया है, लेकिन अनबॉक्सिंग ऑपरेशन को स्पष्ट करता है।
जेबी निजेट

1
@JBNizet लोग उस विधि कॉल foo(int i)नहीं लिखते foo(myInteger.intValue());हर बार वे इसे (या कम से कम मुझे नहीं उम्मीद !!)। मैं आपके साथ सहमत हूं जो Integer::intValueअधिक स्पष्ट है लेकिन मुझे लगता है कि यहां भी यही लागू होता है। लोगों को बस इसे एक बार सीखना चाहिए और फिर आपको :-) यह ऐसा नहीं है जैसे कि यह कुछ जादूई आक्षेप था।
एलेक्सिस सी।

4
@JB Nizet: ठीक है, i -> iनो-सेशन और conceptionally की तरह दिखता है, यह है एक नहीं-op। ज़रूर, हुड के नीचे Integer.intValue()बुलाया जाता है, लेकिन हुड के नीचे और भी गहरा, उस तरीके को बिल्कुल नो-ऑप बनने के लिए इनबिल्ट हो जाता है जो कि सोर्स कोड में दिखता है। Integer::intValueबाइट कोड में सिंथेटिक विधि नहीं बनाने का बोनस बिंदु है, लेकिन यह नहीं है कि आपके स्रोत कोड को कैसे व्यवस्थित किया जाए, इसके बारे में आपका निर्णय लेना चाहिए।
होल्गर

जवाबों:


498

यह काम करेगा, लेकिन i -> iकुछ स्वत: unboxing कर रहा है यही कारण है कि यह "अजीब" लगता है। निम्नलिखित में से कोई भी काम करेगा और बेहतर समझाएगा कि कंपाइलर आपके मूल सिंटैक्स के साथ हुड के नीचे क्या कर रहा है:

integers.values().stream().mapToInt(i -> i.intValue()).sum();
integers.values().stream().mapToInt(Integer::intValue).sum();

2
अगर हमारे पास BigInteger :) हो तो क्या होगा?
GOXR3PLUS 12

13
एक सरल विकल्प हैBigDecimal sum = numbers.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
मैथ्यू

158

मेरा सुझाव है 2 और विकल्प:

integers.values().stream().mapToInt(Integer::intValue).sum();
integers.values().stream().collect(Collectors.summingInt(Integer::intValue));

दूसरा एक Collectors.summingInt()कलेक्टर का उपयोग करता है , एक summingLong()कलेक्टर भी है जिसे आप उपयोग करेंगे mapToLong


और एक तीसरा विकल्प: जावा 8 LongAdderसमानांतर धाराओं और बहु-थ्रेड वातावरण में गति-अप करने के लिए डिज़ाइन किए गए एक बहुत प्रभावी संचायक का परिचय देता है। यहाँ, यहाँ एक उदाहरण का उपयोग करें:

LongAdder a = new LongAdder();
map.values().parallelStream().forEach(a::add);
sum = a.intValue();

86

से डॉक्स

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

बेशक, ऐसे कार्यों को सरल अनुक्रमिक छोरों के रूप में आसानी से लागू किया जा सकता है, जैसे कि:

int sum = 0;
for (int x : numbers) {
   sum += x;
}

हालांकि, उपरोक्त के रूप में एक उत्परिवर्ती संचय पर कम संचालन को प्राथमिकता देने के लिए अच्छे कारण हैं। न केवल एक कमी "अधिक सार" है - यह व्यक्तिगत तत्वों के बजाय एक पूरे के रूप में धारा पर काम करता है - लेकिन एक उचित रूप से निर्मित कम करने वाला ऑपरेशन स्वाभाविक रूप से समानांतर है, इसलिए जब तक तत्वों को संसाधित करने के लिए उपयोग किए जाने वाले फ़ंक्शन (एस) होते हैं और स्टेटलेस। उदाहरण के लिए, संख्याओं की एक धारा दी गई है जिसके लिए हम योग प्राप्त करना चाहते हैं, हम लिख सकते हैं:

int sum = numbers.stream().reduce(0, (x,y) -> x+y);

या:

int sum = numbers.stream().reduce(0, Integer::sum);

ये कमी ऑपरेशन लगभग बिना किसी संशोधन के समानांतर चल सकते हैं:

int sum = numbers.parallelStream().reduce(0, Integer::sum);

तो, आपके द्वारा उपयोग किए जाने वाले नक्शे के लिए:

integers.values().stream().mapToInt(i -> i).reduce(0, (x,y) -> x+y);

या:

integers.values().stream().reduce(0, Integer::sum);

2
ओपी के पास क्या बेहतर है, और यह भी स्पष्ट है। इस कोड में पूरी तरह से अनबॉक्सिंग और बॉक्सिंग ऑपरेशन शामिल होंगे।
जेबी निजेट

1
@ जेबीएनज़ेट जब तक बच विश्लेषण बॉक्सिंग को समाप्त नहीं करता है। आपको यह देखने की कोशिश करनी होगी कि क्या यह हो सकता है।
पीटर लॉरी

6
(x, y) -> x + y को x और y को अनबॉक्स करने की आवश्यकता है, उन्हें योग करें, और फिर परिणाम बॉक्स करें। और धारा के अगले तत्व के साथ परिणाम को जोड़ने के लिए फिर से शुरू करें, और फिर से।
जेबी निज़ेट

3
पूर्णांक :: योग एक ही समस्या से ग्रस्त है। और यदि आप एक IntStream करने के लिए mapToInt () का उपयोग करते हैं, तो इस पर कॉलिंग योग () कॉल को कम करने () से अधिक सीधा है।
जेबी निज़ात

3
Docs.oracle.com/javase/8/docs/api/java/lang/… देखें । Integer.sum () के दो तर्क प्रकार के हैं। तो धारा से दो इंटेगर को विधि के तर्क के रूप में पारित करने के लिए अनबॉक्स किया जाना चाहिए। विधि एक इंट रिटर्न देती है, लेकिन कम () तर्क के रूप में एक बाइनरीऑपरेटर <Integer> लेती है, जो इस प्रकार एक इंटेगर देता है। इसलिए राशि के परिणाम को इंटेगर पर बॉक्स करना होगा।
जेबी निज़ात

28

आप कम करने की विधि का उपयोग कर सकते हैं:

long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, (x, y) -> x + y);

या

long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, Integer::sum);

9
इसके लिए पहले से ही ऐसा संचायक है int, यह हैInteger::sum
एलेक्स सलाउउ

1
आप लंबे समय से लौट रहे हैं, इसलिए यह बेहतर Long::sumहोगा Integer::sum
आंद्रेई डेमियन-फ़ेकेट


11

पूर्णांकों की सूची जोड़ने के लिए आप कलेक्ट विधि का उपयोग कर सकते हैं।

List<Integer> list = Arrays.asList(2, 4, 5, 6);
int sum = list.stream().collect(Collectors.summingInt(Integer::intValue));

6

यह योग करने के लिए सबसे छोटा रास्ता होगा int(के लिए प्रकार सरणी longसरणी LongStreamके लिए, doubleसरणी DoubleStreamऔर आगे)। Streamहालांकि सभी आदिम पूर्णांक या फ्लोटिंग पॉइंट प्रकारों का कार्यान्वयन नहीं होता है।

IntStream.of(integers).sum();

दुर्भाग्य से हमारे पास कोई अंतर-सरणी नहीं है। तो IntStream.of()जब तक कि हम इस तरह की दिशा में कुछ डरावना इस समस्या के लिए काम नहीं करेगा,:IntStream.of( integers.values().stream().mapToInt( Integer::intValue ).toArray() ).sum();
कापलान

कोई जरूरत नहीं, यह पर्याप्त होगा integers.values().stream().mapToInt( Integer::intValue ).sum()
सचिन डिकवेला

3

यह उन लोगों की मदद कर सकता है जिनके पास सूची में ऑब्जेक्ट हैं।

यदि आपके पास ऑब्जेक्ट्स की एक सूची है और इस ऑब्जेक्ट के विशिष्ट क्षेत्रों का योग करना चाहते हैं, तो नीचे का उपयोग करें।

List<ResultSom> somList = MyUtil.getResultSom();
BigDecimal result= somList.stream().map(ResultSom::getNetto).reduce(
                                             BigDecimal.ZERO, BigDecimal::add);

धन्यवाद, इससे मेरी
स्कीनियो

1

मैंने इंटेगर की एक सूची घोषित की है।

ArrayList<Integer> numberList = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5));

आप नीचे इन विभिन्न तरीकों का उपयोग करके देख सकते हैं।

का उपयोग करते हुए mapToInt

int sum = numberList.stream().mapToInt(Integer::intValue).sum();

का उपयोग करते हुए summarizingInt

int sum = numberList.stream().collect(Collectors.summarizingInt(Integer::intValue)).getSum();

का उपयोग करते हुए reduce

int sum = numberList.stream().reduce(Integer::sum).get().intValue();

-1
class Pojo{
    int num;

    public Pojo(int num) {
        super();
        this.num = num;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}

List<Pojo> list = new ArrayList<Pojo>();
            list.add(new Pojo(1));
            list.add(new Pojo(5));
            list.add(new Pojo(3));
            list.add(new Pojo(4));
            list.add(new Pojo(5));

            int totalSum = list.stream().mapToInt(pojo -> pojo.getNum()).sum();
            System.out.println(totalSum);

-1

ज्यादातर पहलू कवर किए गए हैं। लेकिन इंटेगर, लॉन्ग (जिसके लिए विशेष स्ट्रीम समर्थन पहले से मौजूद है) के अलावा अन्य डेटा प्रकारों के एकत्रीकरण को खोजने की आवश्यकता हो सकती है। उदाहरण के लिए BigInteger के साथ स्ट्रैम इस प्रकार के लिए हम जैसे कम ऑपरेशन का उपयोग कर सकते हैं

list.stream ()। कम करें ((bigInteger1, bigInteger2) -> bigInteger1.add (bigInteger2))

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