views:

83

answers:

3

PHP's range function work like this in php :

$leap_years = range(1900, 2000, 4);

creates array like 1900, 1904, 1908, ... Is there something simple like this in Java?

+4  A: 

There isn't anything built in for this, but it's relatively simple to implement such a range as an immutable Iterable<Long> (or Integer or whatever). Just create a custom Iterator that starts at the start value and then increment for each call to next() until you pass the end value. You have to decide how and if you want to handle high-to-low iteration and such as well, but it isn't hard. You could also do this as an unmodifiable implementation of List where the value for each index is calculated on demand (start + index * increment).

While your question refers to the creation of an "array" based on the range, an array full of the data on the whole range is often not needed, particularly if you just want to iterate through the numbers in the range. If that's all you want, you'll end up iterating through the numbers in the range twice to create an array or List and then read it. Using a lazy range iterator as I've described doesn't have this disadvantage. Additionally, a lazy iterator can easily be copied into a List if you do want all the values stored in memory directly. The only disadvantage of it in comparison to building an array is some autoboxing overhead.

ColinD
+1  A: 

You could simulate it like this:

public int[] range(int startVal, int endVal, int increment) {
  if (startVal >= endVal) {
    //handle error or add option to go backwards
  }
  int count = ((endval - startval) / increment) + 1;
  int[] myArr = new int[count];
  for (int i=0; i <= count; i++) {
    myArr[i] = startVal + (i * increment);
  }
  return myArr;
 }
}
Drackir
You can't use primitives with generics.
ColinD
`ArrayList<int>` should be `ArrayList<Integer>`
Rocket
Good point, thanks. I don't have Java here at work to test it. :(
Drackir
@Drackir: Oohh. You're on your work: You have to work ;-) Or doesn't it matter if you are working or not? ;-)
Martijn Courteaux
@Drackir: I'm not sure, but... I don't think you can use `ArrayList<Integer>.toArray()` (which returns an `Object[]`) to cast it to, or use it as `int[]`...
Martijn Courteaux
@Martijn: Right, you can't.
ColinD
Does this one work?
Drackir
+2  A: 

You should do it this way:

public int[] range(int start, int end, int increment) {
   if (start < end && increment < 0) throw IllegalArgumentException();
   if (start > end && increment > 0) throw IllegalArgumentException();

   int[] values = new int[Math.abs((end - start) / increment) + 1];
   boolean reverse = start > end;

   for (int i = start, index = 0; reverse ? (i >= end) : (i <= end); i+=increment, ++index)
   {
       values[index] = i;
   }
   return values;
}
Martijn Courteaux
I guess this would not work with reverse ranges like `range(2000, 1000, 100);`.
Willi
@Willi: Indeed, I edited my method, but not tested...
Martijn Courteaux