Java: ¿equivalente al rango de Python (int, int)?

99

¿Java tiene un equivalente al range(int, int)método de Python ?

Nick Heiner
fuente
¿Te refieres a un rango de Python 2.x que devuelve una lista, o un rango de Python 3.x que devuelve un iterador (equivalente al rango x 2.x)? El primero es relativamente simple de implementar como otros lo han hecho a continuación, pero la versión del iterador es un poco más complicada.
Dave Kirby
Para un rango de cualquier Comparables, vea esta respuesta
c0der
Para un rango con pasos, vea esto
Sławomir Lenart

Respuestas:

27

Guava también proporciona algo similar a Python range:

Range.closed(1, 5).asSet(DiscreteDomains.integers());

También puede implementar un iterador bastante simple para hacer el mismo tipo de cosas usando el AbstractIterator de Guava:

return new AbstractIterator<Integer>() {
  int next = getStart();

  @Override protected Integer computeNext() {
    if (isBeyondEnd(next)) {
      return endOfData();
    }
    Integer result = next;
    next = next + getStep();
    return result;
  }
};
Simon Steele
fuente
6
Ojalá hubiera visto esto antes de implementar mi propia gama genérica. Es agradable, pero es otro recordatorio de lo torpe que se puede comparar Java con lenguajes más funcionales.
z7sg Ѫ
14
Range#asSetParece que ha quedado obsoleto. Ahora necesita hacer esto:ContiguousSet.create(Range.closed(low, high), DiscreteDomain.integers())
Proyecto Chthonic
¿Qué biblioteca necesito importar para usar esto?
tgabb
Desde Java 8, IntStream y LongStream tienen métodos range y rangeClosed.
Jose Manuel Gomez Alvarez
225

Pregunta anterior, nueva respuesta (para Java 8)

    IntStream.range(0, 10).forEach(
        n -> {
            System.out.println(n);
        }
    );

o con referencias de métodos:

IntStream.range(0, 10).forEach(System.out::println);
jhodges
fuente
1
Que paquete como lo importo
Justin Thomas
6
@Justin Esa es la característica del lenguaje Java 8.
Tzafrir
16

Desde Guava 15.0, Range.asSet () ha quedado obsoleto y está programado para ser eliminado en la versión 16. Utilice lo siguiente en su lugar:

ContiguousSet.create(Range.closed(1, 5), DiscreteDomain.integers());
jiehanzheng
fuente
15

Estoy trabajando en una pequeña biblioteca de utilidades de Java llamada Jools , y contiene una clase Rangeque proporciona la funcionalidad que necesita (hay un JAR descargable).
Los constructores son o bien Range(int stop), Range(int start, int stop)o Range(int start, int stop, int step)(similar a un bucle for) y usted puede iterar a través de él, el cual utiliza la evaluación perezosa, o puede utilizar su toList()método para obtener explícitamente la lista de rangos.

for (int i : new Range(10)) {...} // i = 0,1,2,3,4,5,6,7,8,9

for (int i : new Range(4,10)) {...} // i = 4,5,6,7,8,9

for (int i : new Range(0,10,2)) {...} // i = 0,2,4,6,8

Range range = new Range(0,10,2);
range.toList(); // [0,2,4,6,8]
Amir Rachum
fuente
14
public int[] range(int start, int stop)
{
   int[] result = new int[stop-start];

   for(int i=0;i<stop-start;i++)
      result[i] = start+i;

   return result;
}

Perdone cualquier error de sintaxis o estilo; Normalmente programo en C #.

KeithS
fuente
Dado que Vivien Barousse se adelantó a una respuesta, ¿por qué no borra la suya para evitar duplicidades? A menos que realmente planees desarrollarlo bien, por supuesto.
aaronasterling
9
Son similares; Creo que el mío es un poco más legible. Su uso de "longitud" es engañoso, y no creo que cumpla con las especificaciones de Python (incluye el límite superior, que network-theory.co.uk/docs/pytut/rangeFunction.html dice que no ocurre en Python ). Si cree que uno es un engañado, creo que tiene la reputación suficiente para enfrentarse a él.
KeithS
10

Puede utilizar el siguiente fragmento de código para obtener un conjunto de rangos de enteros:

    Set<Integer> iset = IntStream.rangeClosed(1, 5).boxed().collect
            (Collectors.toSet());
Julian
fuente
7
public int[] range(int start, int length) {
    int[] range = new int[length - start + 1];
    for (int i = start; i <= length; i++) {
        range[i - start] = i;
    }
    return range;
}

(Respuesta larga solo para decir "No")

Vivien Barousse
fuente
Además, vea que "rango" en Python 3 y el "xrange" preferido en Python 2 devuelven un objeto "en vivo" que no usa memoria para cada elemento que contiene. Eso sería aún más grande de implementar en Java.
jsbueno
3

Java 9 - IntStream::iterate

Desde Java 9 puedes usar IntStream::iteratee incluso puedes personalizar el paso. Por ejemplo, si quieres una intmatriz:

public static int[] getInRange(final int min, final int max, final int step) {
    return IntStream.iterate(min, i -> i < max, i -> i + step)
            .toArray();
}

o bien List:

public static List<Integer> getInRange(final int min, final int max, final int step) {
    return IntStream.iterate(min, i -> i < max, i -> i + step)
            .boxed()
            .collect(Collectors.toList());
}

Y luego úsalo:

int[] range = getInRange(0, 10, 1);
Michalk
fuente
2

La ingeniosa clase Range de Groovy se puede usar desde Java, aunque ciertamente no es tan maravillosa.

Juan
fuente
1

Si tiene la intención de usarlo como lo haría en un bucle de Python, Java funciona bien con la instrucción for, lo que hace que esta estructura sea innecesaria para ese propósito.

Nikki9696
fuente
5
Por lo general, tampoco lo usa para un bucle en Python. Casi siempre hay una forma más limpia de iterar.
Daenyth
Bueno, el rango se usa generalmente en un bucle for. Pero los bucles for se utilizan a menudo sin rango.
FogleBird
1
IntStream.range(0, 10).boxed().collect(Collectors.toUnmodifiableList());
Pierre
fuente
1
Sería útil si explicaras cómo este código resuelve el problema.
Robert Columbia
0

Sé que esta es una publicación antigua, pero si está buscando una solución que devuelva un flujo de objetos y no quiere o no puede usar ninguna dependencia adicional:

Stream.iterate(start, n -> n + 1).limit(stop);

inicio - incluido parada - exclusivo

HDubz
fuente