Tentative d'implémentation de certaines fonctionnalités de reductionRight. Pour les performances, ce serait bien d'itérer de droite à gauche, sans tout inverser d'abord, puis de gauche à droite. Normalement, nous faisons:
ArrayList<...> a = new ArrayList<...>(); // Add elements to list. // Generate an iterator. Start just after the last element. ListIterator li = a.listIterator(a.size()); // Iterate in reverse. while(li.hasPrevious()) { System.out.println(li.previous()); }
mais je cherche quelque chose comme:
Iteratable iterable ...; Iterator iterator = iterable.reverseIterator(); iterator.next();
Je vois cette solution: Parcourir une liste dans l'ordre inverse en Java
La réponse acceptée actuelle dit que cela fonctionne:
Iteratable iterable ...; Iterator iterator = iterable.iterator(); iterator.next();
Quelqu'un sait comment implémenter l'itération inverse avec seulement un Iterable
en main? Je n'ai pas de ArrayList
ou List en main, j'ai un Iterable
en main. Je suppose que je peux convertir l'Iterable en ArrayList, inverser la liste, puis obtenir un itérateur, mais ce ne serait pas amusant :)
3 Réponses :
Vous devrez parcourir une fois l ' itérateur
original pour construire un itérateur
inversé (en supposant que votre itérateur
original est fini) .
Par exemple:
static <T> Iterator<T> getReversedIterator(Iterable<T> iterable) { Iterator<T> iter = iterable.iterator(); List<T> rev = new ArrayList<>(); while (iter.hasNext()) { rev.add (0, iter.next()); } return rev.iterator(); }
Réponse simple: impossible de manière générique et performante.
L'essence de l'itérateur est de vous donner une direction, pas les deux. Et imaginez une liste uniquement liée. Cette chose n'a vraiment "qu'une seule direction"!
Donc, la question de savoir comment inverser une chose itérable vous oblige vraiment à regarder l'implémentation exacte. Sans cette possibilité, vous devez utiliser une structure de données intermédiaire pour récupérer toutes les entrées avant d'annuler.
Si vous avez un Iterable
en main, comme vous l'avez écrit dans votre question, quelqu'un vous l'a fourni. Je suggérerais de demander au fournisseur de fournir un Iterable
qui prend en charge l'itération inverse.
Cela ou implémentez simplement réduire et n'implémentez pas reductionRight et attendez-vous à ce qu'ils aient la liste dans le bon ordre. Mais je pense que c'est bien de faire le travail pour l'utilisateur de la lib.
Vous ne pouvez pas. Iterator ne prend en charge la traversée que dans une seule direction. Vous devrez copier les éléments dans une pile et les faire apparaître. Étant donné que vous essayez d'atteindre des performances, je ne ferais pas cela - voyez si vous pouvez repeindre votre réduction dans l'autre sens.
@BoristheSpider ouais c'est ce que j'ai pensé, étant donné les informations dans OP, pouvez-vous donner la meilleure solution possible? Merci
N'oubliez pas qu'un
Iterable
peut être théoriquement infini. C'est pourquoi cela ne peut pas être pris en charge au niveau de l'API. Vous devez utiliser une structure de données qui prend en charge les traversées inverses.@JoeC c'est pour une bibliothèque donc essayer de prendre en charge autant de types de données que possible en utilisant
Iterable
github.com/google/guava/issues/980 si vous avez le temps, sinon simplement utiliser les listes de goyave.newArrayList (iterable) .reverse ()
Le point de @ JoeC est bon à garder à l'esprit - les deux
Stream
etIterator
peuvent être infinis; prenezIterators.cycle
de Guava par exemple. J'éviterais d'exposer une API qui permet des choses que vous ne pouvez pas prendre en charge.