Étant donné Iterator<Element>
, comment pouvons-nous convertir cette Iterator
en ArrayList<Element>
(ou List<Element>
) de la manière meilleure et rapide possible, afin que nous puissions utiliser les opérations de ArrayList
telles que get(index)
, add(element)
, etc.
Mieux vaut utiliser une bibliothèque comme Guava :
import com.google.common.collect.Lists;
Iterator<Element> myIterator = ... //some iterator
List<Element> myList = Lists.newArrayList(myIterator);
Un autre exemple de goyave:
ImmutableList.copyOf(myIterator);
ou Collections Apache Commons :
import org.Apache.commons.collections.IteratorUtils;
Iterator<Element> myIterator = ...//some iterator
List<Element> myList = IteratorUtils.toList(myIterator);
En Java 8, vous pouvez utiliser la nouvelle méthode forEachRemaining
qui a été ajoutée à l'interface Iterator
:
List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);
Vous pouvez copier un itérateur dans une nouvelle liste comme celle-ci:
Iterator<String> iter = list.iterator();
List<String> copy = new ArrayList<String>();
while (iter.hasNext())
copy.add(iter.next());
Cela suppose que la liste contient des chaînes. Il n'y a pas vraiment de moyen plus rapide de recréer une liste à partir d'un itérateur, vous êtes obligé de la parcourir manuellement et de copier chaque élément dans une nouvelle liste du type approprié.
MODIFIER :
Voici une méthode générique pour copier un itérateur dans une nouvelle liste de manière sécurisée:
public static <T> List<T> copyIterator(Iterator<T> iter) {
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
Utilisez-le comme ceci:
List<String> list = Arrays.asList("1", "2", "3");
Iterator<String> iter = list.iterator();
List<String> copy = copyIterator(iter);
System.out.println(copy);
> [1, 2, 3]
Vous pouvez également utiliser IteratorUtils
from Apache commons-collections , bien qu'il ne prenne pas en charge les génériques:
List list = IteratorUtils.toList(iterator);
Notez qu'il existe une différence entre Iterable
et Iterator
.
Si vous avez Iterable
, avec Java 8, vous pouvez utiliser cette solution:
Iterable<Element> iterable = createIterable();
List<Element> array = StreamSupport
.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
Comme je le sais, Collectors.toList()
crée une instance ArrayList
.
En fait, à mon avis, cela semble également bon dans une ligne.
Par exemple, si vous devez renvoyer List<Element>
depuis une méthode:
return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList());
Solution assez concise avec Java 8 simple utilisant Java.util.stream
:
public static <T> ArrayList<T> toArrayList(final Iterator<T> iterator) {
return StreamSupport
.stream(
Spliterators
.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
.collect(
Collectors.toCollection(ArrayList::new)
);
}
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
La méthode Java 8 forEachRemaining dans Iterator peut être utilisée ici:
List<Element> elementList = new ArrayList<>();
iterator.forEachRemaining(elementList::add);
Essayez StickyList
from Cactoos :
List<String> list = new StickyList<>(iterator);
Disclaimer: Je suis l'un des développeurs.
utilisez google goyave !
Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);
++
Je veux simplement signaler une solution apparemment évidente qui ne fonctionnera PAS:
List list = Stream.generate (iterator :: next) .collect (Collectors.toList ());
C'est parce que Stream#generate(Supplier<T>)
ne peut créer que des flux infinis, il ne s'attend pas à ce que son argument jette NoSuchElementException
(c'est ce que Iterator#next()
fera à la fin).
La réponse du xehpuk devrait être utilisée à la place si la méthode Itérateur → Flux → Liste est votre choix.