Um iterador não corresponde necessariamente a algo com uma "contagem" ...
Oliver Charlesworth
Os iteradores são o que são; para iterar para o próximo objeto de uma coleção (pode ser qualquer coisa como set, array, etc.) Por que eles precisam dizer o tamanho quando não se importam com o que estão tentando iterar? to provide an implementation-independent method for access, in which the user does not need to know whether the underlying implementation is some form of array or of linked list, and allows the user go through the collection without explicit indexing.penguin.ewu.edu/~trolfe/LinkedSort/Iterator.html
ecle
Respostas:
67
Se você acabou de obter o iterador, isso é o que você terá que fazer - ele não sabe quantos itens faltam para iterar, então você não pode consultá-lo para aquele resultado. Existem métodos utilitários que parecem fazer isso (como Iterators.size()no Guava), mas por baixo eles estão apenas executando aproximadamente a mesma operação.
No entanto, muitos iteradores vêm de coleções, que geralmente você pode consultar por seu tamanho. E se você está obtendo o iterador para uma classe criada pelo usuário, pode fornecer um método size () nessa classe.
Resumindo, na situação em que você tem apenas o iterador, não há maneira melhor, mas muito mais frequentemente do que não, você tem acesso à coleção ou objeto subjacente a partir do qual pode ser capaz de obter o tamanho diretamente.
Cuidado com o efeito colateral de Iterators.size(...)(mencionado em outros comentários abaixo e em java-doc): "Retorna o número de elementos restantes no iterador. O iterador ficará esgotado: seu método hasNext () retornará falso." Isso significa que você não pode mais usar o Iterator depois disso. Lists.newArrayList(some_iterator);pode ajudar.
Usando a biblioteca Guava , outra opção é converter o Iterablepara um List.
List list =Lists.newArrayList(some_iterator);int count = list.size();
Use-o se também precisar acessar os elementos do iterador após obter seu tamanho. Ao usar, Iterators.size()você não pode mais acessar os elementos iterados.
@LoveToCode Menos eficiente do que o exemplo da pergunta original
Inverno
2
Claro, criar um novo objeto com todos os elementos é mais lento do que apenas iterar e descartar. IMHO, esta solução é uma linha que melhora a legibilidade do código. Eu o uso muito para coleções com poucos elementos (até 1000) ou quando a velocidade não é um problema.
tashuhka
7
Se tudo o que você tem é o iterador, então não, não há maneira "melhor". Se o iterador vier de uma coleção, você poderá definir o tamanho.
Lembre-se de que o Iterator é apenas uma interface para percorrer valores distintos, você muito bem teria um código como este
newIterator<Long>(){finalRandom r =newRandom();@Overridepublicboolean hasNext(){returntrue;}@OverridepublicLong next(){return r.nextLong();}@Overridepublicvoid remove(){thrownewIllegalArgumentException("Not implemented");}};
ou
newIterator<BigInteger>(){BigInteger next =BigInteger.ZERO;@Overridepublicboolean hasNext(){returntrue;}@OverridepublicBigInteger next(){BigInteger current = next;
next = next.add(BigInteger.ONE);return current;}@Overridepublicvoid remove(){thrownewIllegalArgumentException("Not implemented");}};
Não há maneira mais eficiente se tudo o que você tem é o iterador. E se o iterador só puder ser usado uma vez, obter a contagem antes de obter o conteúdo do iterador é ... problemático.
A solução é alterar seu aplicativo para que não precise da contagem ou obter a contagem por algum outro meio. (Por exemplo, passe um em Collectionvez de Iterator...)
to provide an implementation-independent method for access, in which the user does not need to know whether the underlying implementation is some form of array or of linked list, and allows the user go through the collection without explicit indexing.
penguin.ewu.edu/~trolfe/LinkedSort/Iterator.htmlRespostas:
Se você acabou de obter o iterador, isso é o que você terá que fazer - ele não sabe quantos itens faltam para iterar, então você não pode consultá-lo para aquele resultado. Existem métodos utilitários que parecem fazer isso (como
Iterators.size()
no Guava), mas por baixo eles estão apenas executando aproximadamente a mesma operação.No entanto, muitos iteradores vêm de coleções, que geralmente você pode consultar por seu tamanho. E se você está obtendo o iterador para uma classe criada pelo usuário, pode fornecer um método size () nessa classe.
Resumindo, na situação em que você tem apenas o iterador, não há maneira melhor, mas muito mais frequentemente do que não, você tem acesso à coleção ou objeto subjacente a partir do qual pode ser capaz de obter o tamanho diretamente.
fonte
Iterators.size(...)
(mencionado em outros comentários abaixo e em java-doc): "Retorna o número de elementos restantes no iterador. O iterador ficará esgotado: seu método hasNext () retornará falso." Isso significa que você não pode mais usar o Iterator depois disso.Lists.newArrayList(some_iterator);
pode ajudar.Usando a biblioteca Guava :
Internamente, ele itera todos os elementos, então é apenas por conveniência.
fonte
Seu código apresentará uma exceção quando você chegar ao final do iterador. Você poderia fazer:
Se você tivesse acesso à coleção subjacente, seria capaz de chamar
coll.size()
...EDITAR OK, você alterou ...
fonte
Você sempre terá que iterar. No entanto, você pode usar Java 8, 9 para fazer a contagem sem repetir explicitamente:
Aqui está um teste:
Isso imprime:
Interessante, você pode paralelizar a operação de contagem aqui, alterando o
parallel
sinalizador nesta chamada:fonte
Usando a biblioteca Guava , outra opção é converter o
Iterable
para umList
.Use-o se também precisar acessar os elementos do iterador após obter seu tamanho. Ao usar,
Iterators.size()
você não pode mais acessar os elementos iterados.fonte
Se tudo o que você tem é o iterador, então não, não há maneira "melhor". Se o iterador vier de uma coleção, você poderá definir o tamanho.
Lembre-se de que o Iterator é apenas uma interface para percorrer valores distintos, você muito bem teria um código como este
ou
fonte
Não há maneira mais eficiente se tudo o que você tem é o iterador. E se o iterador só puder ser usado uma vez, obter a contagem antes de obter o conteúdo do iterador é ... problemático.
A solução é alterar seu aplicativo para que não precise da contagem ou obter a contagem por algum outro meio. (Por exemplo, passe um em
Collection
vez deIterator
...)fonte
para Java 8 você pode usar,
fonte
O objeto iterator contém o mesmo número de elementos que sua coleção continha.
Mas em vez de obter o tamanho do iterador e iterar pelo índice 0 até esse tamanho, é melhor iterar por meio do método next () do iterador.
fonte
a
, mas apenasi
?