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 forEachRemaining
método que foi adicionado à Iterator
interface:
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/…
iterator
vem? é 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 Iterable
e 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 ArrayList
instâ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.
Iterator
volta 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 Collector
não melhora a legibilidade nesse caso, pois ela precisa ser suportada por a Stream
e a Spliterator
.
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
Experimente StickyList
no 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 runs
takes 40 ms
onde, 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.
for
loop 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.