49

Is there any syntax/package allowing quick filling of java arrays with ranges of numbers, like in perl?

e.g.

int[] arr = new int[1000];
arr=(1..500,301..400,1001..1400); // returns [1,2,3,4,...,500,301,302,...,400,1001,1002,...1400]

Also, it here a package that allows getting the n-th number in such list of numbers as the above, without actually creating the array (which can be huge)?

e.g.

BunchOfRangesType bort = new BunchOfRangesType("1..500","301..400","1001..1400");
bort.get(0); // return 1
bort.get(500); // return 301
bort.get(501); // return 302

It's not too difficult to implement, but I guess it might be common so maybe it was already done.

apaderno
  • 28,547
  • 16
  • 75
  • 90
David B
  • 29,258
  • 50
  • 133
  • 186

7 Answers7

141

For those still looking for a solution:

In Java 8 or later, this can be answered trivially using Streams without any loops or additional libraries.

int[] range = IntStream.rangeClosed(1, 10).toArray();

This will produce an array with the integers from 1 to 10.

A more general solution that produces the same result is below. This can be made to produce any sequence by modifying the unary operator.

int[] range = IntStream.iterate(1, n -> n + 1).limit(10).toArray();
Craig
  • 4,492
  • 2
  • 19
  • 22
  • in JDK-9 the last variant can be `int[] range = IntStream.iterate(1, n -> n <= 10, n -> n + 1).toArray();`. – Ousmane D. Jul 27 '18 at 22:44
  • 5
    for those (like me) who want to have the resulting range in a List you can use the `IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList())` (credit to https://stackoverflow.com/questions/23674624/how-do-i-convert-a-java-8-intstream-to-a-list) – Abdu Jan 15 '19 at 19:24
  • 1
    `IntStream` is available for API LEVEL 24+ (Android Studio). What solution as simple as that do we have for API LEVEL below 24? – Aliton Oliveira Oct 16 '19 at 23:15
18

There is dollar:

// build the List 10, 11, 12, 13, 14
List<Integer> list2 = $(10, 15).toList();

maven:

<dependency>
        <groupId>org.bitbucket.dollar</groupId>
        <artifactId>dollar</artifactId>
        <version>1.0-beta3</version>
</dependency>
Suzker
  • 15
  • 1
  • 8
True Soft
  • 8,675
  • 6
  • 54
  • 83
  • I can't find anything like this either. This is only valid in Java if you define the $ method yourself. – Erick Robertson Aug 02 '10 at 13:10
  • 2
    After further review, it appears that "dollar" is a library which defines the $ method as a static method of a Dollar class. With the link dead, it's nearly impossible to actually find the code to this. So this answer is pretty useless. Full java syntax would require calling this as Dollar.$(10, 15).toList(). – Erick Robertson Aug 02 '10 at 13:17
  • @Erick, yes, `$` is a method. What do you mean by *'the link dead'*? The source code for this library is available, too. – True Soft Aug 02 '10 at 13:26
  • 1
    @Erick - not if you `import static com.humaorie.dollar.Dollar.*`. – Andrzej Doyle Aug 02 '10 at 13:47
  • @True Soft: The bitbucket.org link is dead. So currently, nothing is available. @Andrzej: Just because you can, doesn't mean you should. At issue is code clarity. No performance is gained by doing that, just code obfuscation. – Erick Robertson Aug 02 '10 at 14:30
  • 1
    The link is ok. I mean, if I click on the link in my answer, I go to that page. – True Soft Aug 02 '10 at 14:45
  • @AikoV3, maybe they removed it from BitBucket. A blog post about this is http://adamldavis.com/post/26847919076/dollar-java-api-that-unifies-collections-arrays – True Soft Apr 22 '13 at 19:23
  • So, we want to use a package for creating a range-array? – BairDev Aug 19 '22 at 13:41
18

Another useful and not widely known Java 8 solution for existing arrays:

int[] array = new int[10];
Arrays.setAll(array, i -> i + 1);
Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
8

As for the first question, whether it is possible to fill an array with the values of a range: it is actually possible to achieve that with the combination of Range, DiscreteDomain, ContiguousSet and Ints from Guava:

int[] array = Ints.toArray(
    ContiguousSet.create(Range.closed(1, 500), DiscreteDomain.integers()));

And, not exactly what is mentioned in the second part of the question, but it is possible to create a set with the elements of a range of a discrete domain:

Set<Integer> numbersFrom1To500 = 
    ContiguousSet.create(Range.closed(1, 500), DiscreteDomain.integers());

The resulting Set will not contain the specified elements physically, only logically (so it's memory footprint will be small), but can be iterated (since it's a Set):

for (Integer integer : numbersFrom1To500) {
    System.out.println(integer);
}
Katona
  • 4,816
  • 23
  • 27
7

Not quite as clean as True Soft's answer, but you can use Google Guava to the same effect:

public class Test {

    public static void main(String[] args) {
        //one liner
        int[] array = toArray(newLinkedList(concat(range(1, 10), range(500, 1000))));

        //more readable
        Iterable<Integer> values = concat(range(1, 10), range(500, 1000));
        List<Integer> list = newLinkedList(values);
        int[] array = toArray(list);

    }

    public static List<Integer> range(int min, int max) {
        List<Integer> list = newLinkedList();
        for (int i = min; i <= max; i++) {
            list.add(i);
        }

        return list;
    }

}

Note you need a few static imports for this to work.

Jared Russell
  • 10,804
  • 6
  • 30
  • 31
  • 1
    Even if more verbose, that's much much clearer than the dollar approach. – Noel M Aug 02 '10 at 12:28
  • I don't think static imports are very clean. I would prefer a custom implementation than to do this. – Erick Robertson Aug 02 '10 at 13:12
  • @Erick "I don't think static imports are very clean." You can of course use the fully qualified method names, however using the static imports does make the code less verbose. – Jared Russell Aug 02 '10 at 14:03
  • Verbosity can improve readability, which is desired. I always reference the class name when calling static methods. I want to make it as easy as possible for the next programmer to understand. I don't see a benefit to making the code less verbose, or compact enough to fit in one line. These things do nothing to improve performance, and only obfuscate the code. – Erick Robertson Aug 02 '10 at 14:32
  • 5
    "Note you need a few static imports for this to work" it would have been helpfull to include them in your code. range(...) can be found in com.google.common.collect.Range toArray(Range) can be found in com.google.common.collect.Iterables newLinkedList(..) can be found in com.google.common.collect.Lists – pveeckhout Apr 19 '13 at 11:10
3
    List<Integer> arrayOfRange  = new ArrayList<Integer>();
    int[] range = IntStream.iterate(1, n -> {arrayOfRange.add(n);return n + 1;}).limit(10).toArray();

// in addition to what craig answer if you want to have Integer 2nd approch

List<Integer> list = IntStream.of(range).boxed().collect(Collectors.toList());
Arun Pratap Singh
  • 3,428
  • 30
  • 23
0
 public static int[] getRangeArray(int start, int end){
        final int[] rangeArray = new int[end-start + 1];
            for(int i = 0; i < rangeArray.length; i++){
                rangeArray[i] = start + i;
          }
       return rangeArray; // It includes start and end values as well, pls adjust according to your need
  }
beginner
  • 2,366
  • 4
  • 29
  • 53