Existe uma maneira curta e agradável de gerar um List<Integer>
, ou talvez um Integer[]
ou int[]
, com valores seqüenciais de algum start
valor para um end
valor?
Ou seja, algo menor que, mas equivalente a 1 o seguinte:
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;
}
O uso de goiaba é bom.
Atualizar:
Análise de desempenho
Como esta pergunta recebeu várias boas respostas, usando bibliotecas Java 8 nativas 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:
- classicArrayList : o código fornecido acima na minha pergunta (e essencialmente o mesmo que a resposta de adarshr).
- eclipseCollections : o código fornecido na resposta de Donald abaixo usando o Eclipse Collections 8.0.
- guavaRange : o código fornecido na resposta daveb abaixo. Tecnicamente, isso não cria um,
List<Integer>
mas sim umContiguousSet<Integer>
- mas, como é implementadoIterable<Integer>
em ordem, funciona principalmente para meus propósitos. - intStreamRange : o código fornecido na resposta de Vladimir abaixo, que usa
IntStream.rangeClosed()
- que foi introduzido no Java 8. - streamIterate : o código fornecido na resposta do Catalin abaixo, que também usa a
IntStream
funcionalidade introduzida no Java 8.
Aqui estão os resultados em operações de quilo 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 que não sejam Eclipse e Guava são muito lentas para obter uma única barra de pixels! As soluções rápidas são 10.000 a 20.000 vezes mais rápidas que as demais.
O que está acontecendo aqui, é claro, é que as soluções goiaba e eclipse realmente não materializam nenhum tipo de lista de 10.000 elementos - elas são simplesmente invólucros de tamanho fixo em torno do ponto inicial e final. Cada elemento é criado conforme necessário durante a iteração. Como na verdade não iteramos neste teste, o custo é adiado. Todas as outras soluções, na verdade, materializam a lista completa na memória e pagam um preço muito alto em uma referência apenas para criação.
Vamos fazer algo um pouco mais realista e também iterar sobre todos os números inteiros, somando-os. Portanto, no caso da IntStream.rangeClosed
variante, a referência se parece com:
@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;
}
Aqui, as imagens mudam bastante, embora as soluções não materializantes ainda sejam as mais rápidas. Aqui está o comprimento = 10:
... e comprimento = 10.000:
A longa iteração sobre muitos elementos equilibra bastante as coisas, mas o eclipse e a goiaba permanecem mais que o dobro da velocidade, mesmo no teste de 10.000 elementos.
Portanto, se você realmente deseja List<Integer>
, coleções de eclipses parece ser a melhor escolha - mas é claro que se você usar fluxos de maneira mais nativa (por exemplo, esquecendo .boxed()
e fazendo uma redução no domínio primitivo), provavelmente terminará mais rápido do que todos esses variantes.
1 Talvez, com exceção do tratamento de erros, por exemplo, se end
< begin
, ou se o tamanho exceder alguns limites de implementação ou JVM (por exemplo, matrizes maiores que 2^31-1
.
fonte
Respostas:
Com o Java 8, é tão simples que nem precisa mais de um método separado:
fonte
Bem, esse liner pode se qualificar (usa Guava Ranges )
Isso não cria um
List<Integer>
, masContiguousSet
oferece a mesma funcionalidade, em particular a implementação,Iterable<Integer>
que permite aforeach
implementação da mesma maneira queList<Integer>
.Nas versões mais antigas (em algum lugar anterior ao Guava 14), você poderia usar isso:
Ambos produzem:
fonte
asList()
lá, a menos que você realmente precisasse deList
... oContiguousSet
produzido porasSet
é leve (ele só precisa do intervalo e do domínio), masasList()
criará uma lista que realmente armazena todos os elementos na memória (atualmente).Range
existe , mas não,Ranges
e eles acabaram com oasSet
método. Na minha versão mais antiga,asSet
está obsoleta e parece que eles a removeram. Aparentemente, as faixas devem ser usadas apenas para coleções contíguas e elas foram aplicadas, embora eu adore esta solução.A seguinte versão do Java 8 de uma linha gerará [1, 2, 3 ... 10]. O primeiro argumento de
iterate
é o primeiro n da sequência e o primeiro argumento delimit
é o último número.fonte
Você pode usar a
Interval
classe das Coleções Eclipse .A
Interval
classe é preguiçosa, portanto, não armazena todos os valores.Seu método poderá ser implementado da seguinte maneira:
Se você deseja evitar o encaixotamento de ints como números inteiros, mas ainda assim desejar uma estrutura de lista como resultado, poderá usá
IntList
-loIntInterval
no Eclipse Collections.IntList
tem os métodossum()
,min()
,minIfEmpty()
,max()
,maxIfEmpty()
,average()
emedian()
disponível na interface.Atualização para maior clareza: 27/11/2017
An
Interval
é umList<Integer>
, mas é preguiçoso e imutável. É extremamente útil para gerar dados de teste, especialmente se você lida muito com coleções. Se você quiser, pode facilmente copiar um intervalo de umList
,Set
ouBag
como se segue:An
IntInterval
é umImmutableIntList
que se estendeIntList
. Também possui métodos de conversão.An
Interval
e anIntInterval
não têm o mesmoequals
contrato.Atualização para o Eclipse Collections 9.0
Agora você pode criar coleções primitivas a partir de fluxos primitivos. Existem métodos
withAll
eofAll
dependendo da sua preferência. Se você está curioso, explico por que temos os dois aqui . Esses métodos existem para listas, conjuntos, malas e pilhas int / longa / dupla mutáveis e imutáveis.Nota: Eu sou um confirmador das Coleções Eclipse
fonte
Este é o mais curto que pude obter usando o Core Java.
fonte
for(int i = begin; i <= end; ret.add(i++));
:)ret.add(i)
peça para o incremento do loop for o torne "mais curto". Eu acho que por essa lógica, se eu escrevi tudo em uma linha que seria mais curto :)Você poderia usar intervalos de goiaba
Você pode obter um
SortedSet
usandofonte
Este é o mais curto que pude encontrar.
Versão da lista
Versão da matriz
fonte
Este pode funcionar para você ....
fonte