Existe-t-il un moyen court et simple de générer un List<Integer>
, ou peut-être un Integer[]
ou int[]
, avec des valeurs séquentielles d'une start
valeur à une end
valeur?
C'est-à-dire quelque chose de plus court que, mais équivalent à 1, ce qui suit:
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 très bien.
Mettre à jour:
Analyse de performance
Étant donné que cette question a reçu plusieurs bonnes réponses, à la fois en utilisant Java 8 natif et des bibliothèques tierces, j'ai pensé tester les performances de toutes les solutions.
Le premier test teste simplement la création d'une liste de 10 éléments en [1..10]
utilisant les méthodes suivantes:
- classicArrayList : le code donné ci-dessus dans ma question (et essentiellement le même que la réponse d'adarshr).
- eclipseCollections : le code donné dans la réponse de Donald ci-dessous en utilisant Eclipse Collections 8.0.
- guavaRange : le code donné dans la réponse de daveb ci-dessous. Techniquement, cela ne crée pas un
List<Integer>
mais plutôt unContiguousSet<Integer>
- mais comme il implémenteIterable<Integer>
dans l'ordre, cela fonctionne principalement pour mes besoins. - intStreamRange : le code donné dans la réponse de Vladimir ci-dessous, qui utilise
IntStream.rangeClosed()
- qui a été introduit dans Java 8. - streamIterate : le code donné dans la réponse de Catalin ci-dessous qui utilise également des
IntStream
fonctionnalités introduites dans Java 8.
Voici les résultats en kilo-opérations par seconde (les nombres plus élevés sont meilleurs), pour tout ce qui précède avec des listes de taille 10:
... et encore pour les listes de taille 10 000:
Ce dernier graphique est correct - les solutions autres que Eclipse et Guava sont trop lentes pour même obtenir une seule barre de pixels! Les solutions rapides sont 10 000 à 20 000 fois plus rapides que les autres.
Ce qui se passe ici, bien sûr, c'est que les solutions de goyave et d'éclipse ne matérialisent en fait aucune sorte de liste de 10000 éléments - ce sont simplement des enveloppes de taille fixe autour des points de départ et d'arrivée. Chaque élément est créé selon les besoins lors de l'itération. Puisque nous n'itérons pas réellement dans ce test, le coût est différé. Toutes les autres solutions matérialisent en fait la liste complète en mémoire et paient un lourd tribut dans un benchmark de création uniquement.
Faisons quelque chose d'un peu plus réaliste et itérons également sur tous les nombres entiers, en les additionnant. Donc, dans le cas de la IntStream.rangeClosed
variante, le benchmark ressemble à:
@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 sont toujours les plus rapides. Voici longueur = 10:
... et longueur = 10 000:
La longue itération sur de nombreux éléments égalise beaucoup les choses, mais l'éclipse et la goyave restent plus de deux fois plus rapides même sur le test de 10000 éléments.
Donc, si vous voulez vraiment une List<Integer>
collection, éclipse semble être le meilleur choix - mais bien sûr, si vous utilisez les flux de manière plus native (par exemple, en oubliant .boxed()
et en réduisant le domaine primitif), vous finirez probablement plus vite que tous ceux-ci. variantes.
1 Peut-être à l'exception de la gestion des erreurs, par exemple, si end
< begin
, ou si la taille dépasse certaines limites d'implémentation ou de JVM (par exemple, des tableaux plus grands que 2^31-1
.
la source
Réponses:
Avec Java 8, c'est si simple qu'il n'a même plus besoin de méthode séparée:
la source
Eh bien, cette doublure pourrait être admissible (utilise des gammes de goyaves )
Cela ne crée pas de
List<Integer>
, maisContiguousSet
offre à peu près les mêmes fonctionnalités, en particulier la mise en œuvreIterable<Integer>
qui permet laforeach
mise en œuvre de la même manière queList<Integer>
.Dans les anciennes versions (quelque part avant Guava 14), vous pouvez utiliser ceci:
Les deux produisent:
la source
asList()
moins que vous n'ayez vraiment besoin d'unList
... leContiguousSet
produit parasSet
est léger (il a juste besoin de la plage et du domaine), maisasList()
créerai une liste qui stocke réellement tous les éléments en mémoire (actuellement).Range
existe mais pasRanges
et ils ont éliminé laasSet
méthode. Dans mon ancienne version,asSet
est obsolète et il semble qu'ils l'ont supprimé. Les plages ne doivent apparemment être utilisées que pour les collections contiguës et elles l'ont appliquée bien que j'adore cette solution.La version Java 8 à une ligne suivante générera [1, 2, 3 ... 10]. Le premier argument de
iterate
est le premier nr de la séquence et le premier arg delimit
est le dernier nombre.la source
Vous pouvez utiliser la
Interval
classe d' Eclipse Collections .La
Interval
classe est paresseuse, donc ne stocke pas toutes les valeurs.Votre méthode pourrait être implémentée comme suit:
Si vous souhaitez éviter de boxer des entiers en tant que nombres entiers, mais que vous souhaitez toujours une structure de liste en conséquence, vous pouvez utiliser
IntList
avecIntInterval
des collections Eclipse.IntList
a les méthodessum()
,min()
,minIfEmpty()
,max()
,maxIfEmpty()
,average()
etmedian()
disponible sur l'interface.Mise à jour pour plus de clarté: 27/11/2017
An
Interval
est unList<Integer>
, mais il est paresseux et immuable. C'est extrêmement utile pour générer des données de test, surtout si vous traitez beaucoup avec des collections. Si vous le souhaitez, vous pouvez facilement copier un intervalle dans unList
,Set
ouBag
comme suit:Un
IntInterval
est unImmutableIntList
qui s'étendIntList
. Il a également des méthodes de conversion.An
Interval
et anIntInterval
n'ont pas le mêmeequals
contrat.Mise à jour pour Eclipse Collections 9.0
Vous pouvez désormais créer des collections primitives à partir de flux primitifs. Il existe
withAll
et desofAll
méthodes en fonction de vos préférences. Si vous êtes curieux, j'explique pourquoi nous avons les deux ici . Ces méthodes existent pour les listes, ensembles, sacs et piles int / longs / doubles mutables et immuables.Remarque: je suis un committer pour les collections Eclipse
la source
C'est le plus court que je puisse obtenir en utilisant Core Java.
la source
for(int i = begin; i <= end; ret.add(i++));
:)ret.add(i)
partie dans l'incrément de boucle for rende cela "plus court". Je suppose que par cette logique, si j'écrivais tout sur une seule ligne, ce serait plus court :)Vous pouvez utiliser des gammes de goyaves
Vous pouvez obtenir un
SortedSet
en utilisantla source
C'est le plus court que j'ai pu trouver.
Version de la liste
Version de la baie
la source
Celui-ci pourrait fonctionner pour vous ...
la source