Como posso gerar uma lista ou matriz de inteiros sequenciais em Java?
Existe uma maneira curta e doce de gerar umList<Integer>
ou talvez umInteger[]
ouint[]
, com valores sequenciais de algunsstart
valor para umend
valor?
Ou seja, algo menor que, mas equivalente a1 Os seguintes:
<code>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; } </code>
O uso de goiaba é bom.
Atualizar:
Análise de desempenhoComo essa pergunta recebeu várias boas respostas, usando bibliotecas nativas do Java 8 e de terceiros, pensei em testar o desempenho de todas as soluções.
O primeiro teste simplesmente testa a criação de uma lista de 10 elementos[1..10]
usando os seguintes métodos:
List<Integer>
mas sim umContiguousSet<Integer>
- mas desde que implementaIterable<Integer>
em ordem, funciona principalmente para meus propósitos.intStreamRange: o código dado emA resposta de Vladimir abaixo, que usaIntStream.rangeClosed()
- que foi introduzido no Java 8.streamIterate: o código dado emCatalin's answer abaixo que também usaIntStream
funcionalidade introduzida no Java 8.Aqui estão os resultados em kilo-operações por segundo (números maiores são melhores), para todos os itens acima com listas de tamanho 10:
... e novamente para listas de tamanho 10.000:
Esse último gráfico está correto - as soluções além do Eclipse e do Guava são muito lentas para obter uma única barra de pixels! As soluções rápidas são de 10.000 a 20.000vezes mais rápido que o resto.
O que está acontecendo aqui, é claro, é que as soluções de goiaba e eclipse não materializam realmente nenhum tipo de lista de 10.000 elementos - eles são simplesmente empacotadores de tamanho fixo em torno dos pontos inicial e final. Cada elemento é criado conforme necessário durante a iteração. Como na verdade não fazemos iteração neste teste, o custo é diferido. Todas as outras soluções realmente materializam a lista completa na memória e pagam um preço alto em uma referência somente de criação.
Vamos fazer algo um pouco mais realista e também iterar todos os inteiros, somando-os. Então, no caso doIntStream.rangeClosed
variante, o benchmark se parece com:
<code>@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; } </code>
Aqui, as imagens mudam muito, embora as soluções não materializantes ainda sejam as mais rápidas. Aqui está o comprimento = 10:
... e comprimento = 10.000:
A longa interação sobre muitos elementos aumenta bastante as coisas, mas o eclipse e a goiaba permanecem duas vezes mais rápidos, mesmo no teste de 10.000 elementos.
Então, se vocêrealmente quer umList<Integer>
, as coleções do eclipse parecem ser a melhor escolha - mas, claro, se você usar os fluxos de uma forma mais nativa (por exemplo, esquecendo.boxed()
e fazendo uma redução no domínio primitivo) você provavelmente acabará mais rápido que todas essas variantes.
1 Talvez com exceção do tratamento de erros, por exemplo, seend
< begin
ou se o tamanho exceder alguns limites de implementação ou de JVM (por exemplo, matrizes maiores que2^31-1
.