Java: Equivalente ao intervalo do Python (int, int)?

99

Java tem um equivalente ao range(int, int)método do Python ?

Nick Heiner
fonte
Você quer dizer um intervalo Python 2.x que retorna uma lista ou um intervalo Python 3.x que retorna um iterador (equivalente a 2.x xrange)? O primeiro é relativamente simples de implementar, como outros fizeram abaixo, mas a versão do iterador é um pouco mais complicada.
Dave Kirby
Para uma faixa de qualquer Comparables, veja esta resposta
c0der
Para um intervalo com stepping veja isto
Sławomir Lenart

Respostas:

27

O Guava também fornece algo semelhante ao do Python range:

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

Você também pode implementar um iterador bastante simples para fazer o mesmo tipo de coisa usando AbstractIterator do 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
fonte
6
Eu gostaria de ter visto isso antes de implementar minha própria linha genérica. É bom, mas ainda outro lembrete de como o Java desajeitado pode ser comparado a linguagens mais funcionais.
z7sg Ѫ
14
Range#asSetparece ter se tornado obsoleto. Agora você precisa fazer isso:ContiguousSet.create(Range.closed(low, high), DiscreteDomain.integers())
Projeto Chthonic
que biblioteca preciso importar para usar isso?
tgabb
No Java 8, IntStream e LongStream têm os métodos range e rangeClosed.
Jose Manuel Gomez Alvarez
225

Pergunta antiga, nova resposta (para Java 8)

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

ou com referências de método:

IntStream.range(0, 10).forEach(System.out::println);
Jhodges
fonte
1
Qual pacote? como faço para importar?
Justin Thomas
6
@Justin Esse é um recurso da linguagem java 8.
Tzafrir
16

Desde o Guava 15.0, Range.asSet () se tornou obsoleto e está programado para ser removido na versão 16. Use o seguinte:

ContiguousSet.create(Range.closed(1, 5), DiscreteDomain.integers());
Jiehanzheng
fonte
15

Estou trabalhando em uma pequena biblioteca de utilitários Java chamada Jools , e ela contém uma classe Rangeque fornece a funcionalidade de que você precisa (há um JAR para download).
Construtores são ou Range(int stop), Range(int start, int stop)ou Range(int start, int stop, int step)(semelhante a um loop) e você pode iterate através dele, que costumava avaliação preguiçosa, ou você pode usar o seu toList()método para obter explicitamente a lista de gama.

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
fonte
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;
}

Perdoe quaisquer erros de sintaxe ou estilo; Eu normalmente programo em C #.

KeithS
fonte
dado que Vivien Barousse chegou antes de você, por que não deleta a sua para evitar qualquer engano. A menos que você realmente planeje aprimorá-lo, é claro.
aaronasterling
9
Eles são semelhantes; Acho que o meu é um pouco mais legível. Seu uso de "comprimento" é enganoso e não acho que ele atenda às especificações do Python (ele inclui o limite superior, que network-theory.co.uk/docs/pytut/rangeFunction.html diz que não acontece no Python ) Se você acha que alguém é um ingênuo, acredito que tem reputação suficiente para lidar com isso sozinho.
KeithS
10

Você pode usar o seguinte snippet de código para obter um conjunto de intervalo de inteiros:

    Set<Integer> iset = IntStream.rangeClosed(1, 5).boxed().collect
            (Collectors.toSet());
Julian
fonte
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;
}

(Resposta longa apenas para dizer "Não")

Vivien Barousse
fonte
Além disso, veja que "range" em Python 3 e o "xrange" preferido em Python 2 retornam um objeto "live" que não usa memória para cada item que contém. Isso seria ainda maior para implementar em Java.
jsbueno
3

Java 9 - IntStream::iterate

Desde o Java 9 você pode usar IntStream::iteratee até personalizar a etapa. Por exemplo, se você deseja intarray:

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

ou 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());
}

E então use-o:

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

A elegante classe Range do Groovy pode ser usada em Java, embora certamente não seja tão legal.

John
fonte
1

Se você pretende usá-lo como faria em um loop Python, o Java executa um loop bem com a instrução for, o que torna essa estrutura desnecessária para esse propósito.

Nikki9696
fonte
5
Você normalmente não o usa para um loop em python. Quase sempre há uma maneira mais limpa de iterar.
Daenyth
Bem, range geralmente é usado em um loop for. Mas os loops for são freqüentemente usados ​​sem intervalo.
FogleBird
1
IntStream.range(0, 10).boxed().collect(Collectors.toUnmodifiableList());
Pierre
fonte
1
Ajudaria se você explicasse como esse código resolve o problema.
Robert Columbia
0

Eu sei que esta é uma postagem antiga, mas se você está procurando uma solução que retorna um fluxo de objeto e não deseja ou não pode usar nenhuma dependência adicional:

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

início - parada inclusiva - exclusivo

HDubz
fonte