Respostas:
Melhor usar uma biblioteca como o Guava :
import com.google.common.collect.Lists;
Iterator<Element> myIterator = ... //some iterator
List<Element> myList = Lists.newArrayList(myIterator);
Outro exemplo de goiaba:
ImmutableList.copyOf(myIterator);
ou Apache Commons Collections :
import org.apache.commons.collections.IteratorUtils;
Iterator<Element> myIterator = ...//some iterator
List<Element> myList = IteratorUtils.toList(myIterator);
No Java 8, você pode usar o novo forEachRemainingmétodo que foi adicionado à Iteratorinterface:
List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);
::? que nome tem isso? parece uma referência direta a list.add (); e parece também alguma coisa nova em java8; e obrigado! :)
::sintaxe é nova no Java 8 e refere-se a uma "referência de método", que é uma forma abreviada de uma lambda. Veja aqui para obter mais informações: docs.oracle.com/javase/tutorial/java/javaOO/…
iteratorvem? é um símbolo não resolvido
iterator.
Você pode copiar um iterador para uma nova lista como esta:
Iterator<String> iter = list.iterator();
List<String> copy = new ArrayList<String>();
while (iter.hasNext())
copy.add(iter.next());
Isso pressupõe que a lista contenha cadeias. Realmente não existe uma maneira mais rápida de recriar uma lista a partir de um iterador, você deve atravessá-la manualmente e copiar cada elemento para uma nova lista do tipo apropriado.
EDIT:
Aqui está um método genérico para copiar um iterador para uma nova lista de uma maneira segura para o tipo:
public static <T> List<T> copyIterator(Iterator<T> iter) {
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
Use-o assim:
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]
Observe que há uma diferença entre Iterablee Iterator.
Se você possui um Iterable, então com o Java 8 você pode usar esta solução:
Iterable<Element> iterable = createIterable();
List<Element> array = StreamSupport
.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
Como eu sei Collectors.toList()cria ArrayListinstância.
Na verdade, na minha opinião, também fica bem em uma linha.
Por exemplo, se você precisar retornar List<Element>de algum método:
return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList());
Iterable iterator. Eles são completamente diferentes.
Iteratorvolta para um único uso Iterable usando () -> iterator. Isso pode ser útil em situações como essa, mas deixe-me enfatizar o importante novamente: você pode usar esse método apenas se um único uso Iterable for aceitável. Ligar iterable.iterator()mais de uma vez produzirá resultados inesperados. A resposta acima é entãoIterator<Element> iterator = createIterator(); List<Element> array = StreamSupport.stream(((Iterable<Element>) () -> iterable).spliterator(), false).collect(toList());
Você também pode usar as coleções comunsIteratorUtils do Apache , embora ele não suporte genéricos:
List list = IteratorUtils.toList(iterator);
Solução bastante concisa com Java 8 simples usando 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)
);
}
iterator.forEachRemaining( list::add ), também novo no Java 8, é muito mais conciso. Pressionar a variável da lista para dentro Collectornão melhora a legibilidade nesse caso, pois ela precisa ser suportada por a Streame a Spliterator.
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
Experimente StickyListno Cactoos :
List<String> list = new StickyList<>(iterable);
Disclaimer: Eu sou um dos desenvolvedores.
Iterable! =Iterator
Eu só quero apontar uma solução aparentemente óbvia que NÃO funcionará:
Lista de lista = Stream.generate (iterator :: next) .collect (Collectors.toList ());
Isso porque Stream#generate(Supplier<T>)pode criar apenas fluxos infinitos, não espera que seu argumento seja lançado NoSuchElementException(é o que Iterator#next()fará no final).
A resposta do xehpuk deve ser usada se a opção Iterador → Fluxo → Lista for a sua escolha.
use o google goiaba !
Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);
++
Aqui, neste caso, se você quiser o caminho mais rápido possível, então for loopé melhor.
O iterador sobre um tamanho de amostra de 10,000 runstakes 40 msonde, quanto ao loop, leva2 ms
ArrayList<String> alist = new ArrayList<String>();
long start, end;
for (int i = 0; i < 1000000; i++) {
alist.add(String.valueOf(i));
}
ListIterator<String> it = alist.listIterator();
start = System.currentTimeMillis();
while (it.hasNext()) {
String s = it.next();
}
end = System.currentTimeMillis();
System.out.println("Iterator start: " + start + ", end: " + end + ", delta: "
+ (end - start));
start = System.currentTimeMillis();
int ixx = 0;
for (int i = 0; i < 100000; i++) {
String s = alist.get(i);
}
System.out.println(ixx);
end = System.currentTimeMillis();
System.out.println("for loop start: " + start + ", end: " + end + ", delta: "
+ (end - start));
Isso pressupõe que a lista contenha cadeias.
forloop e acessar os elementos de uma lista get(i)é mais rápido do que usar um iterador ... mas não era isso que o OP estava pedindo, ele mencionou especificamente que um iterador é fornecido como entrada.
get(int)loop, você está olhando apenas 100k das entradas de 1m. Se você alterar esse loop it.size(), verá que esses dois métodos estão próximos da mesma velocidade. Em geral, esses tipos de testes de velocidade do java fornecem informações limitadas sobre o desempenho na vida real e devem ser vistos com ceticismo.