Convertir un tableau Java en Iterable

J’ai un tableau de primitives, par exemple pour int, int [] foo. Ce pourrait être une petite taille ou non.

int foo[] = {1,2,3,4,5,6,7,8,9,0}; 

Quelle est la meilleure façon de créer un Iterable ?

 Iterable fooBar = convert(foo); 

Remarques:

S’il vous plaît ne répondez pas en utilisant des boucles (sauf si vous pouvez donner une bonne explication sur la façon dont le compilateur fait quelque chose d’intelligent à leur sujet?)

Notez également que

 int a[] = {1,2,3}; List l = Arrays.asList(a); 

Ne comstackra même pas

 Type mismatch: cannot convert from List to List 

Vérifiez également pourquoi un tableau ne peut pas être assigné à Iterable? avant de répondre.

En outre, si vous utilisez une bibliothèque (par exemple, Guava), veuillez expliquer pourquoi il s’agit du meilleur. (Parce que sa de Google n’est pas une réponse complète: P)

Enfin, comme il semble y avoir un devoir à ce sujet, évitez d’afficher le code du travail à domicile.

 Integer foo[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; List list = Arrays.asList(foo); // or Iterable iterable = Arrays.asList(foo); 

Bien que vous deviez utiliser un tableau Integer (pas un tableau int ) pour que cela fonctionne.

Pour les primitives, utilisez Guava:

 Iterable fooBar = Ints.asList(foo); 
  com.google.guava guava 15.0 jar  

juste mes 2 centimes:

 final int a[] = {1,2,3}; java.lang.Iterable aIterable=new Iterable() { public Iterator iterator() { return new Iterator() { private int pos=0; public boolean hasNext() { return a.length>pos; } public Integer next() { return a[pos++]; } public void remove() { throw new UnsupportedOperationException("Cannot remove an element of an array."); } }; } }; 

Avec Java 8, vous pouvez le faire.

 final int[] arr = {1, 2, 3}; final PrimitiveIterator.OfInt i1 = Arrays.stream(arr).iterator(); final PrimitiveIterator.OfInt i2 = IntStream.of(arr).iterator(); final Iterator i3 = IntStream.of(arr).boxed().iterator(); 

Guava fournit l’adaptateur que vous voulez en tant que Int.asList () . Il y a un équivalent pour chaque type primitif dans la classe associée, par exemple, Booleans pour boolean , etc.

 int foo[] = {1,2,3,4,5,6,7,8,9,0}; Iterable fooBar = Ints.asList(foo); for(Integer i : fooBar) { System.out.println(i); } 

Les suggestions ci-dessus pour utiliser Arrays.asList ne fonctionneront pas, même si elles sont compilées car vous obtenez un Iterator plutôt qu’un Iterator . Qu’est-ce qui se passe est que, plutôt que de créer une liste sauvegardée par votre tableau, vous avez créé une liste de tableaux à un élément, contenant votre tableau.

J’ai eu le même problème et l’ai résolu comme ceci:

 final YourType[] yourArray = ...; return new Iterable() { public Iterator iterator() { return Iterators.forArray(yourArray); // Iterators is a Google guava utility } } 

L’iterator lui-même est un UnmodifiableIterator paresseux mais c’est exactement ce dont j’avais besoin.

Vous pouvez utiliser IterableOf partir de Cactoos :

 Iterable names = new IterableOf<>( "Scott Fitzgerald", "Fyodor Dostoyevsky" ); 

Ensuite, vous pouvez le transformer en une liste en utilisant ListOf :

 List names = new ListOf<>( new IterableOf<>( "Scott Fitzgerald", "Fyodor Dostoyevsky" ) ); 

Ou simplement ceci:

 List names = new ListOf<>( "Scott Fitzgerald", "Fyodor Dostoyevsky" ); 

Tout d’abord, je ne peux qu’être d’accord sur le fait Arrays.asList(T...) est clairement la meilleure solution pour les types ou les tableaux Wrapper avec des types de données non primitifs. Cette méthode appelle un constructeur d’une simple implémentation AbstractList statique statique privée dans la classe Arrays , qui enregistre essentiellement la référence de tableau donnée en tant que champ et simule une liste en remplaçant les méthodes nécessaires.

Si vous pouvez choisir entre un type primitif ou un type Wrapper pour votre tableau, j’utiliserais le type Wrapper pour de telles situations, mais bien sûr, ce n’est pas toujours utile ou nécessaire. Il n’y aurait que deux possibilités:

1) Vous pouvez créer une classe avec une méthode statique pour chaque tableau de types de données primitif ( boolean, byte, short, int, long, char, float, double retourne une Iterable< WrapperType > . Ces méthodes utiliseraient des classes anonymes d’ Iterator (outre Iterable ) qui sont autorisés à contenir la référence de l'argument de la méthode comprenant (par exemple un int[] ) en tant que champ afin d'implémenter les méthodes.

-> Cette approche est performante et vous permet d’économiser de la mémoire (à l’exception de la mémoire des méthodes nouvellement créées, même si l’utilisation d’ Arrays.asList() prend la même mémoire)

2) Les tableaux n'ayant pas de méthodes (à lire sur le côté que vous avez lié), ils ne peuvent pas non plus fournir d'instance d' Iterator . Si vous êtes vraiment trop paresseux pour écrire de nouvelles classes, vous devez utiliser une instance d'une classe déjà existante qui implémente Iterable car il n'y a pas d'autre solution que l'instanciation d' Iterable ou d'un sous-type.
La SEULE façon de créer une dérivée Collection existante implémentant Iterable consiste à utiliser une boucle (sauf que vous utilisez des classes anonymes comme décrit ci-dessus) ou vous instanciez une classe d'implémentation Iterable dont le constructeur autorise un tableau de type primtive ( Object[] n'autorisant pas les tableaux) avec des éléments de type primitif) mais pour autant que je sache, l’API Java ne comporte pas de classe comme celle-là.

La raison de la boucle peut être expliquée facilement:
pour chaque collection, les objects et les types de données primtive ne sont pas des objects. Les objects sont beaucoup plus gros que les types primitifs, de sorte qu'ils nécessitent des données supplémentaires qui doivent être générées pour chaque élément du tableau de type primitif. Cela signifie que si deux méthodes sur trois (en utilisant Arrays.asList(T...) ou en utilisant une collection existante) nécessitent un agrégat d'objects, vous devez créer pour chaque valeur primitive de votre tableau int[] l'object wrapper. La troisième méthode utiliserait le tableau tel quel et l’utiliserait dans une classe anonyme car je pense qu’il est préférable en raison des performances rapides.

Il y a aussi une troisième stratégie utilisant un Object comme argument pour la méthode où vous voulez utiliser le tableau ou Iterable et cela nécessiterait des vérifications de type pour déterminer le type de l'argument, mais je ne le recommanderais pas du tout comme d'habitude Vous devez considérer que l'object n'a pas toujours le type requirejs et que vous avez besoin d'un code distinct pour certains cas.

En conclusion, c'est la faute du système de type générique problématique de Java qui ne permet pas d'utiliser des types primitifs comme type générique, ce qui permettrait d'économiser beaucoup de code en utilisant simplement Arrays.asList(T...) . Donc, vous devez programmer pour chaque tableau de type primitif, vous avez besoin d'une telle méthode (qui ne fait fondamentalement aucune différence avec la mémoire utilisée par un programme C ++ qui créerait pour chaque argument de type utilisé une méthode distincte).

Bien qu’une réponse similaire ait déjà été publiée, je pense que la raison d’utiliser le nouveau PrimitiveIterator.OfInt n’était pas claire. Une bonne solution consiste à utiliser Java 8 PrimitiveIterator car il est spécialisé pour les types int primitifs (et évite les pénalités supplémentaires de boxing / unboxing):

  int[] arr = {1,2,3}; // If you use Iterator here as type then you can't get the actual benefit of being able to use nextInt() later PrimitiveIterator.OfInt iterator = Arrays.stream(arr).iterator(); while (iterator.hasNext()) { System.out.println(iterator.nextInt()); // Use nextInt() instead of next() here to avoid extra boxing penalty } 

Réf: https://doc.bccnsoft.com/docs/jdk8u12-docs/api/java/util/PrimitiveIterator.OfInt.html

Dans java8 IntSteam stream peut être encadré pour diffuser des entiers.

 public static Iterable toIterable(int[] ints) { return IntStream.of(ints).boxed().collect(Collectors.toList()); } 

Je pense que la performance est importante en fonction de la taille du tableau.