Existe-t-il un moyen simple et rapide de générer un List<Integer>
ou peut-être un Integer[]
o int[]
avec des valeurs séquentielles de certains start
à une valeur end
valeur ?
C'est-à-dire quelque chose de plus court, mais d'équivalent à 1 les éléments suivants :
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;
}
L'utilisation de la goyave est une bonne chose.
Mise à jour :
Analyse des performances
Comme cette question a reçu plusieurs bonnes réponses, utilisant à la fois la version native de Java 8 et des bibliothèques tierces, j'ai pensé tester les performances de toutes les solutions.
Le premier test consiste simplement à tester la création d'une liste de 10 éléments [1..10]
à l'aide des méthodes suivantes :
- classicArrayList Le code donné ci-dessus dans ma question (et essentiellement le même que celui de la réponse d'adarshr).
- eclipseCollections le code donné dans l'article Réponse de Donald ci-dessous en utilisant Eclipse Collections 8.0.
- guavaRange le code donné dans l'article Réponse de daveb ci-dessous. Techniquement, cela ne crée pas de
List<Integer>
mais plutôt unContiguousSet<Integer>
- mais comme il met en œuvreIterable<Integer>
dans l'ordre, cela fonctionne en grande partie pour mes besoins. - intStreamRange le code donné dans l'article Réponse de Vladimir ci-dessous, qui utilise
IntStream.rangeClosed()
- qui a été introduite dans Java 8. - streamIterate le code donné dans l'article Réponse de Catalin ci-dessous qui utilise également
IntStream
introduite dans Java 8.
Voici les résultats en kilo-opérations par seconde (les chiffres les plus élevés sont les meilleurs), pour toutes les opérations ci-dessus avec des listes de taille 10 :
... et à nouveau pour des listes de 10 000 :
Le dernier graphique est exact - les solutions autres qu'Eclipse et Guava sont trop lentes pour obtenir une barre d'un seul pixel ! Les solutions rapides sont de 10 000 à 20 000 fois plus rapide que les autres.
Ce qui se passe ici, bien sûr, c'est que les solutions guava et eclipse ne matérialisent pas réellement une liste de 10 000 éléments - il s'agit simplement d'enveloppes de taille fixe autour des points de départ et d'arrivée. Chaque élément est créé au fur et à mesure des besoins au cours de l'itération. Comme nous n'itérons pas dans ce test, le coût est reporté. Toutes les autres solutions matérialisent en fait la liste complète en mémoire et paient un lourd tribut dans un test de référence portant uniquement sur la création.
Faisons quelque chose d'un peu plus réaliste et itérons également sur tous les entiers, en les additionnant. Ainsi, dans le cas du IntStream.rangeClosed
l'indice de référence se présente comme suit :
@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;
}
Ici, les images changent beaucoup, même si les solutions non matérialisantes restent les plus rapides. Voici la longueur = 10 :
... et longueur = 10 000 :
La longue itération sur un grand nombre d'éléments égalise les choses, mais eclipse et guava restent plus de deux fois plus rapides même sur le test de 10 000 éléments.
Ainsi, si vous vraiment veulent un List<Integer>
Les collections eclipse semblent être le meilleur choix - mais bien sûr, si vous utilisez les flux d'une manière plus native (par exemple, en oubliant la fonction .boxed()
et en effectuant une réduction dans le domaine primitif), vous serez probablement plus rapide que toutes ces variantes.
1 Peut-être à l'exception de la gestion des erreurs, par exemple si end
< begin
ou si la taille dépasse certaines limites de l'implémentation ou de la JVM (par exemple, les tableaux plus grands que 2^31-1
.