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


130

वहाँ एक उत्पन्न करने के लिए एक छोटा और प्रभावी तरीका है List<Integer>, या शायद एक Integer[]या int[]कुछ से अनुक्रमिक मूल्यों के साथ, startएक करने के लिए मूल्य endमूल्य?

यह है, कुछ की तुलना में कम है, लेकिन निम्नलिखित 1 के बराबर है :

void List<Integer> makeSequence(int begin, int end) {
  List<Integer> ret = new ArrayList<>(end - begin + 1);
  for (int i=begin; i<=end; i++) {
    ret.add(i);
  }
  return ret;  
}

अमरूद का उपयोग ठीक है।

अपडेट करें:

क्षमता का परिक्षण

चूँकि इस सवाल को कई अच्छे उत्तर मिले हैं, दोनों में देशी जावा 8 और थर्ड पार्टी लाइब्रेरी का उपयोग किया गया है, मैंने सोचा कि मैं सभी समाधानों के प्रदर्शन का परीक्षण करूँगा।

पहला परीक्षण केवल [1..10]निम्नलिखित विधियों का उपयोग करके 10 तत्वों की एक सूची बनाने का परीक्षण करता है :

  • ClassicArrayList : मेरे प्रश्न में ऊपर दिया गया कोड (और अनिवार्य रूप से adarshr के उत्तर के समान)।
  • eclipseCollections : नीचे दिए गए कोड डोनाल्ड के उत्तर में ग्रहण संग्रह 8.0 का उपयोग करते हुए।
  • guavaRange : नीचे दिए गए daveb के उत्तर में दिया गया कोड । तकनीकी रूप से, यह List<Integer>एक ContiguousSet<Integer>- बल्कि - लेकिन पैदा नहीं करता है, क्योंकि यह Iterable<Integer>क्रम में लागू होता है, यह ज्यादातर मेरे उद्देश्यों के लिए काम करता है।
  • intStreamRange : व्लादिमीर के जवाब में नीचे दिया गया कोड , जो उपयोग करता है IntStream.rangeClosed()- जिसे जावा 8 में पेश किया गया था।
  • streamIterate : नीचे दिए गए कैटलिन के उत्तर में दिया गया कोड, जो IntStreamजावा 8 में शुरू की गई कार्यक्षमता का उपयोग करता है ।

यहां प्रति सेकंड 10 किलो के संचालन में परिणाम (उच्च संख्या बेहतर हैं), उपरोक्त सभी के लिए आकार 10 की सूची के साथ:

सूची निर्माण थ्रूपुट

... और फिर से आकार १०,००० की सूची के लिए:

यहाँ छवि विवरण दर्ज करें

वह अंतिम चार्ट सही है - एक्लिप्स और अमरूद के अलावा अन्य समाधान भी एक पिक्सेल बार पाने के लिए बहुत धीमे हैं! बाकी की तुलना में तेजी से समाधान 10,000 से 20,000 गुना तेज हैं।

यहाँ क्या चल रहा है, निश्चित रूप से, यह है कि अमरूद और ग्रहण समाधान वास्तव में किसी भी तरह के 10,000 तत्व सूची में नहीं आते हैं - वे बस शुरुआत और समापन बिंदु के आसपास निश्चित आकार के रैपर हैं। प्रत्येक तत्व पुनरावृत्ति के दौरान आवश्यकतानुसार बनाया जाता है। चूंकि हम वास्तव में इस परीक्षण में पुनरावृति नहीं करते हैं, इसलिए लागत को स्थगित कर दिया जाता है। अन्य सभी समाधान वास्तव में पूरी सूची को स्मृति में बदल देते हैं और एक निर्माण-केवल बेंचमार्क में भारी कीमत का भुगतान करते हैं।

चलो कुछ और अधिक यथार्थवादी करते हैं और सभी पूर्णांकों पर भी पुनरावृति करते हैं, उन्हें संक्षेप में लिखें। इसलिए IntStream.rangeClosedसंस्करण के मामले में , बेंचमार्क इस तरह दिखता है:

@Benchmark
public int intStreamRange() {
    List<Integer> ret = IntStream.rangeClosed(begin, end).boxed().collect(Collectors.toList());  

    int total = 0;
    for (int i : ret) {
        total += i;
    }
    return total;  
}

यहां, चित्र बहुत बदल जाते हैं, हालांकि गैर-भौतिक समाधान अभी भी सबसे तेज़ हैं। यहाँ लंबाई = 10 है:

सूची <पूर्णांक> परिवर्तन (लंबाई = 10)

... और लंबाई = 10,000:

सूची <पूर्णांक> परिवर्तन (लंबाई = 10,000)

कई तत्वों पर लंबे समय तक चलना चीजों को बहुत बढ़ा देता है, लेकिन 10,000 टन के परीक्षण पर भी ग्रहण और अमरूद दो बार से अधिक तेज रहते हैं।

इसलिए यदि आप वास्तव में एक चाहते हैं List<Integer>, तो ग्रहण संग्रह सबसे अच्छा विकल्प लगता है - लेकिन निश्चित रूप से यदि आप अधिक देशी तरीके से धाराओं का उपयोग करते हैं (जैसे, .boxed()आदिम डोमेन में कमी और भूल कर) तो आप शायद इन सभी की तुलना में तेजी से समाप्त हो जाएंगे। वेरिएंट।


1 शायद त्रुटि से निपटने के अपवाद के साथ, उदाहरण के लिए, यदि end< begin, या यदि आकार कुछ कार्यान्वयन या जेवीएम सीमा से अधिक है (उदाहरण के लिए, इससे बड़ा है) 2^31-1


अपाचे कॉमन्स के लिए, stackoverflow.com/a/5744861/560302
MoveFast

जवाबों:


185

जावा 8 के साथ यह इतना सरल है इसलिए इसे अब अलग विधि की भी आवश्यकता नहीं है:

List<Integer> range = IntStream.rangeClosed(start, end)
    .boxed().collect(Collectors.toList());

2
मैंने लेबल intStreamRange के साथ इस उत्तर के लिए प्रदर्शन परिणाम जोड़े ।
21

API की आवश्यकता 24+
gcantoni

28

खैर, यह एक लाइनर अर्हता प्राप्त कर सकता है ( अमरूद का उपयोग करता है )

ContiguousSet<Integer> integerList = ContiguousSet.create(Range.closedOpen(0, 10), DiscreteDomain.integers());
System.out.println(integerList);

यह एक निर्माण नहीं करता है List<Integer>, लेकिन ContiguousSetबहुत ही कार्यक्षमता प्रदान करता है, विशेष रूप से कार्यान्वयन में Iterable<Integer>जो foreachउसी तरह कार्यान्वयन की अनुमति देता है List<Integer>

पुराने संस्करणों में (गुवा 14 से पहले कहीं) आप इसका उपयोग कर सकते हैं:

ImmutableList<Integer> integerList = Ranges.closedOpen(0, 10).asSet(DiscreteDomains.integers()).asList();
System.out.println(integerList);

दोनों का उत्पादन:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

7
मैं asList()तब तक वहां उपयोग नहीं करूंगा जब तक आपको वास्तव में जरूरत नहीं है List... ContiguousSetउत्पादित द्वारा asSetहल्का होता है (यह सिर्फ सीमा और डोमेन की आवश्यकता है), लेकिन asList()एक सूची बनाएगा जो वास्तव में स्मृति (वर्तमान में) में सभी तत्वों को संग्रहीत करता है।
कॉलिनड

1
माना। ओपी एक सूची या सरणी के लिए पूछ रहा था, अन्यथा मैंने इसे छोड़ दिया होगा
daveb

1
मैं 18.0 के लिए विश्वास करता हूं, Rangeमौजूद है लेकिन नहीं Rangesऔर उन्होंने asSetविधि के साथ किया है । मेरे पुराने संस्करण में, asSetहटा दिया गया है और ऐसा प्रतीत होता है कि उन्होंने इसे हटा दिया है। रंग जाहिरा तौर पर केवल सन्निहित संग्रह के लिए उपयोग किए जाने वाले हैं और उन्होंने इसे लागू किया है, हालांकि मैं इस समाधान से प्यार करता हूं।
डेमोन्गोल

एपीआई को अब इसके समान कोड की आवश्यकता है: ContiguousSet.create (Range.closed (1, count), DiscreteDomain.integers ()
Ben

मैंने इस उत्तर के लिए प्रदर्शन परिणामों को लेबल guavaRange के साथ जोड़ा
21

11

निम्नलिखित एक-लाइनर जावा 8 संस्करण [1, 2, 3 ... 10] उत्पन्न करेगा। iterateअनुक्रम में पहला arg पहला nr है, और limitअंतिम संख्या का पहला arg है।

List<Integer> numbers = Stream.iterate(1, n -> n + 1)
                              .limit(10)
                              .collect(Collectors.toList());

मैंने लेबल स्ट्रीम के साथ ऊपर इस उत्तर के लिए प्रदर्शन परिणाम जोड़े ।
BeeOnRope

1
स्पष्टीकरण के एक बिंदु के रूप में, सीमा आर्ग अंतिम संख्या नहीं है, यह सूची में पूर्णांक की संख्या है।
नीलसिरॉन

7

आप ग्रहण संग्रहोंInterval से कक्षा का उपयोग कर सकते हैं ।

List<Integer> range = Interval.oneTo(10);
range.forEach(System.out::print);  // prints 12345678910

Intervalवर्ग आलसी है, इसलिए सभी मान दुकान नहीं है।

LazyIterable<Integer> range = Interval.oneTo(10);
System.out.println(range.makeString(",")); // prints 1,2,3,4,5,6,7,8,9,10

आपका तरीका निम्नानुसार लागू किया जा सकेगा:

public List<Integer> makeSequence(int begin, int end) {
    return Interval.fromTo(begin, end);
}

आप पूर्णांक के रूप में मुक्केबाजी ints से बचने के लिए चाहते हैं, लेकिन अभी भी एक परिणाम के रूप एक सूची संरचना की तरह है, तो आप उपयोग कर सकते हैं चाहते हैं IntListके साथ IntIntervalग्रहण संग्रह से।

public IntList makeSequence(int begin, int end) {
    return IntInterval.fromTo(begin, end);
}

IntListहै तरीकों sum(), min(), minIfEmpty(), max(), maxIfEmpty(), average()और median()इंटरफेस पर उपलब्ध है।

स्पष्टता के लिए अद्यतन: 11/27/2017

एक Intervalहै List<Integer>, लेकिन यह आलसी और अपरिवर्तनीय है। यह परीक्षण डेटा उत्पन्न करने के लिए बेहद उपयोगी है, खासकर यदि आप संग्रह के साथ बहुत कुछ करते हैं। यदि आप चाहते हैं कि आप एक अंतराल को आसानी से कॉपी कर सकते हैं List, Setया Bagइस प्रकार है:

Interval integers = Interval.oneTo(10);
Set<Integer> set = integers.toSet();
List<Integer> list = integers.toList();
Bag<Integer> bag = integers.toBag();

एक IntIntervalएक है ImmutableIntListजो फैली हुई है IntList। इसमें कन्वर्टर तरीके भी हैं।

IntInterval ints = IntInterval.oneTo(10);
IntSet set = ints.toSet();
IntList list = ints.toList();
IntBag bag = ints.toBag();

एक Intervalऔर एक IntIntervalही equalsअनुबंध नहीं है ।

ग्रहण संग्रह के लिए अद्यतन 9.0

अब आप आदिम धाराओं से आदिम संग्रह बना सकते हैं। कर रहे हैं withAllऔर ofAllअपनी प्राथमिकता के आधार तरीकों। यदि आप उत्सुक हैं, तो मैं समझाता हूं कि हम दोनों यहां क्यों हैं । ये विधियाँ उत्परिवर्तनीय और अपरिवर्तनीय Int / Long / Double Lists, सेट्स, बैग्स और ढेरों के लिए मौजूद हैं।

Assert.assertEquals(
        IntInterval.oneTo(10),
        IntLists.mutable.withAll(IntStream.rangeClosed(1, 10)));

Assert.assertEquals(
        IntInterval.oneTo(10),
        IntLists.immutable.withAll(IntStream.rangeClosed(1, 10)));

नोट: मैं एक्लिप्स कलेक्शंस के लिए कमिट हूं


मैंने इस उत्तर के लिए प्रदर्शन परिणामों को लेबल eclipseCollections के साथ जोड़ा
21

साफ। मैंने एक अतिरिक्त आदिम संस्करण के साथ अपने उत्तर को अपडेट किया जो किसी भी मुक्केबाजी से बचना चाहिए।
डोनाल्ड रबाब

6

यह कोर जावा का उपयोग करने वाला सबसे छोटा है।

List<Integer> makeSequence(int begin, int end) {
  List<Integer> ret = new ArrayList(end - begin + 1);

  for(int i = begin; i <= end; i++, ret.add(i));

  return ret;  
}

3
आप उस लूप को बदलकर एक जोड़े को और अधिक पात्रों को दाढ़ी दे सकते हैं for(int i = begin; i <= end; ret.add(i++));:)
vaughandroid

मुझे वास्तव में यकीन नहीं है कि ret.add(i)लूप वेतन वृद्धि के लिए इस हिस्से को स्थानांतरित करने से यह "छोटा" हो जाता है। मैं उस तर्क से अनुमान लगाता हूं अगर मैंने यह सब एक पंक्ति में लिखा तो यह छोटा होगा :)
मधुमक्खी पालन

@BeeOnRope हां, निश्चित रूप से सबसे छोटी नहीं, लेकिन सुनिश्चित करने के लिए दो पंक्तियों से छोटा है :) जैसा कि मैंने कहा, यह निकटतम है हम कोर जावा में इसे छोटा करने के लिए आ सकते हैं।
अदर्सहर

मैं लेबल के साथ ऊपर इस उत्तर के लिए प्रदर्शन के परिणामों जोड़ा classicArrayList
21

3

आप अमरूद का उपयोग कर सकते हैं

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

ImmutableSortedSet<Integer> set = Ranges.open(1, 5).asSet(DiscreteDomains.integers());
// set contains [2, 3, 4]

0

यह सबसे छोटा है जो मुझे मिल सकता है।

सूची का संस्करण

public List<Integer> makeSequence(int begin, int end)
{
    List<Integer> ret = new ArrayList<Integer>(++end - begin);

    for (; begin < end; )
        ret.add(begin++);

    return ret;
}

ऐरे संस्करण

public int[] makeSequence(int begin, int end)
{
    if(end < begin)
        return null;

    int[] ret = new int[++end - begin];
    for (int i=0; begin < end; )
        ret[i++] = begin++;
    return ret;
}

-2

यह आपके लिए काम कर सकता है ...।

void List<Integer> makeSequence(int begin, int end) {

  AtomicInteger ai=new AtomicInteger(begin);
  List<Integer> ret = new ArrayList(end-begin+1);

  while ( end-->begin) {

    ret.add(ai.getAndIncrement());

  }
  return ret;  
}

मेरे परीक्षण में लगभग दस बार धीमी गति से, परमाणुओं के लिए AtomicInteger का उपयोग करना बहुत भारी है। लेकिन यह मल्टीथ्रेड के लिए सुरक्षित है। अंत < सत्यापित नहीं शुरू करें
cl-r

1
AtomicInteger का उपयोग एक विधि के अंदर समझ में नहीं आता है। एक विधि कॉल में सभी वाक्य क्रमिक रूप से उस थ्रेड द्वारा चलाए जाते हैं जिसे विधि कहा जाता है, इसलिए आपको AtomicInteger से कुछ भी नहीं मिलता है, लेकिन मंदी और कष्टप्रद getAndIncrement () कॉल।
इगोर रोड्रिगेज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.