¿Hay una manera corta y dulce de generar un List<Integer>
, o tal vez un Integer[]
o int[]
, con valores secuenciales de algún start
valor a un end
valor?
Es decir, algo más corto que, pero equivalente a 1, lo siguiente:
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;
}
El uso de la guayaba está bien.
Actualizar:
Análisis de rendimiento
Dado que esta pregunta ha recibido varias buenas respuestas, utilizando tanto Java 8 nativas como bibliotecas de terceros, pensé en probar el rendimiento de todas las soluciones.
La primera prueba simplemente prueba la creación de una lista de 10 elementos [1..10]
utilizando los siguientes métodos:
- classicArrayList : el código dado anteriormente en mi pregunta (y esencialmente el mismo que la respuesta de adarshr).
- eclipseCollections : el código dado en la respuesta de Donald a continuación usando Eclipse Collections 8.0.
- guavaRange : el código dado en la respuesta de daveb a continuación. Técnicamente, esto no crea un
List<Integer>
sino más bien unContiguousSet<Integer>
, pero como se implementaIterable<Integer>
en orden, funciona principalmente para mis propósitos. - intStreamRange : el código proporcionado en la respuesta de Vladimir a continuación, que utiliza
IntStream.rangeClosed()
, que se introdujo en Java 8. - streamIterate : el código proporcionado en la respuesta de Catalin a continuación, que también utiliza la
IntStream
funcionalidad introducida en Java 8.
Aquí están los resultados en kilo-operaciones por segundo (los números más altos son mejores), para todo lo anterior con listas de tamaño 10:
... y nuevamente para listas de tamaño 10,000:
Ese último gráfico es correcto: las soluciones que no sean Eclipse y Guava son demasiado lentas para incluso obtener una sola barra de píxeles. Las soluciones rápidas son 10,000 a 20,000 veces más rápidas que el resto.
Lo que está sucediendo aquí, por supuesto, es que las soluciones de guayaba y eclipse en realidad no materializan ningún tipo de lista de 10,000 elementos, simplemente son envoltorios de tamaño fijo alrededor del inicio y los puntos finales. Cada elemento se crea según sea necesario durante la iteración. Como no realizamos iteraciones en esta prueba, el costo se difiere. Todas las otras soluciones en realidad materializan la lista completa en la memoria y pagan un alto precio en un punto de referencia de solo creación.
Hagamos algo un poco más realista y también iteremos sobre todos los enteros, resumiéndolos. Entonces, en el caso de la IntStream.rangeClosed
variante, el punto de referencia se ve así:
@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;
}
Aquí, las imágenes cambian mucho, aunque las soluciones que no se materializan siguen siendo las más rápidas. Aquí está la longitud = 10:
... y longitud = 10,000:
La larga iteración sobre muchos elementos iguala las cosas mucho, pero el eclipse y la guayaba permanecen más del doble de rápido incluso en la prueba de 10,000 elementos.
Entonces, si realmente desea una List<Integer>
, las colecciones de eclipse parecen ser la mejor opción, pero, por supuesto, si usa secuencias de una manera más nativa (por ejemplo, olvidando .boxed()
y haciendo una reducción en el dominio primitivo), probablemente terminará más rápido que todos estos variantes
1 Quizás con la excepción del manejo de errores, por ejemplo, si end
< begin
, o si el tamaño excede algunos límites de implementación o JVM (por ejemplo, matrices más grandes que 2^31-1
.
fuente
Respuestas:
Con Java 8 es tan simple que ya ni siquiera necesita un método separado:
fuente
Bueno, este trazador de líneas podría calificar (usa gamas de guayaba )
Esto no crea una
List<Integer>
, peroContiguousSet
ofrece la misma funcionalidad, en particular la implementaciónIterable<Integer>
que permite laforeach
implementación de la misma manera queList<Integer>
.En versiones anteriores (en algún lugar antes de Guava 14) podría usar esto:
Ambos producen:
fuente
asList()
allí a menos que realmente necesitaras unList
... elContiguousSet
producido porasSet
es liviano (solo necesita el rango y el dominio), peroasList()
creará una lista que realmente almacena todos los elementos en la memoria (actualmente).Range
existe pero noRanges
y han eliminado elasSet
método. En mi versión anterior,asSet
está en desuso y parece que lo han eliminado. Al parecer, los rangos solo se deben usar para colecciones contiguas y lo han hecho cumplir, aunque me encanta esta solución.La siguiente versión de Java 8 de una línea generará [1, 2, 3 ... 10]. El primer argumento de
iterate
es el primer nr de la secuencia, y el primer argumento delimit
es el último número.fuente
Puede usar la
Interval
clase de Eclipse Collections .La
Interval
clase es perezosa, por lo que no almacena todos los valores.Su método podría implementarse de la siguiente manera:
Si desea evitar las entradas de boxeo como enteros, pero aún así desea una estructura de lista como resultado, puede usarlo
IntList
conIntInterval
Eclipse Collections.IntList
tiene los métodossum()
,min()
,minIfEmpty()
,max()
,maxIfEmpty()
,average()
ymedian()
disponible en la interfaz.Actualización para mayor claridad: 27/11/2017
An
Interval
es aList<Integer>
, pero es vago e inmutable. Es extremadamente útil para generar datos de prueba, especialmente si manejas mucho las colecciones. Si lo desea, puede copiar fácilmente un intervalo en aList
,Set
o de laBag
siguiente manera:Un
IntInterval
es unImmutableIntList
que se extiendeIntList
. También tiene métodos de conversión.An
Interval
y anIntInterval
no tienen el mismoequals
contrato.Actualización para Eclipse Collections 9.0
Ahora puede crear colecciones primitivas a partir de flujos primitivos. Existen
withAll
yofAll
métodos según su preferencia. Si tienes curiosidad, te explico por qué tenemos ambos aquí . Estos métodos existen para listas, conjuntos, bolsas y pilas Int / Long / Double mutables e inmutables.Nota: Soy un committer para Eclipse Collections
fuente
Esto es lo más corto que pude obtener usando Core Java.
fuente
for(int i = begin; i <= end; ret.add(i++));
:)ret.add(i)
parte al incremento for loop lo haga "más corto". Supongo que según esa lógica, si lo escribiera todo en una línea, sería más corto :)Podrías usar gamas de guayaba
Puedes obtener un
SortedSet
usandofuente
Esto es lo más corto que pude encontrar.
Lista de versiones
Versión de matriz
fuente
Este podría funcionar para ti ...
fuente