173 votes

Comment générer une liste ou un tableau d'entiers séquentiels en Java ?

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 un ContiguousSet<Integer> - mais comme il met en œuvre Iterable<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 :

List creation throughput

... et à nouveau pour des listes de 10 000 :

enter image description here

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 :

List<Integer> Iteration (length=10)

... et longueur = 10 000 :

List<Integer> Iteration (length=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 .

4voto

jmruc Points 4686

Vous pouvez utiliser Gammes de goyaves

Vous pouvez obtenir un SortedSet en utilisant

ImmutableSortedSet<Integer> set = Ranges.open(1, 5).asSet(DiscreteDomains.integers());
// set contains [2, 3, 4]

4voto

Venkata Raju Points 174
int[] arr = IntStream.rangeClosed(2, 5).toArray();
System.out.println(Arrays.toString(arr));
// [2, 3, 4, 5]

Integer[] boxedArr = IntStream.rangeClosed(2, 5)
  .boxed().toArray(Integer[]::new);
System.out.println(Arrays.toString(boxedArr));

// Since Java 16
List<Integer> list1 = IntStream.rangeClosed(2, 5)
  .boxed().toList();
System.out.println(list1);

List<Integer> list2 = IntStream.rangeClosed(2, 5)
  .boxed().collect(Collectors.toList());
System.out.println(list2);

List<Integer> list3 = Arrays.asList(boxedArr);
System.out.println(list3);

List<Integer> list4 = new ArrayList<>();
IntStream.rangeClosed(2, 5).forEachOrdered(list4::add);
System.out.println(list4);

0voto

Aung Thaw Aye Points 437

C'est le plus court que j'ai pu trouver.

Version de la liste

public List<Integer> makeSequence(int begin, int end)
{
    List<Integer> ret = new ArrayList<Integer>(++end - begin);

    for (; begin < end; )
        ret.add(begin++);

    return ret;
}

Version de la grille

public int[] makeSequence(int begin, int end)
{
    if(end < begin)
        return null;

    int[] ret = new int[++end - begin];
    for (int i=0; begin < end; )
        ret[i++] = begin++;
    return ret;
}

-2voto

Shehzad Points 1377

Celui-ci pourrait vous convenir....

void List<Integer> makeSequence(int begin, int end) {

  AtomicInteger ai=new AtomicInteger(begin);
  List<Integer> ret = new ArrayList(end-begin+1);

  while ( end-->begin) {

    ret.add(ai.getAndIncrement());

  }
  return ret;  
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X