No meu aplicativo, uso a biblioteca de terceiros (Spring Data for MongoDB para ser exato).
Os métodos desta biblioteca retornam Iterable<T>
, enquanto o restante do meu código esperaCollection<T>
.
Existe algum método utilitário em algum lugar que me permita converter rapidamente um para o outro? Gostaria de evitar a criação de um monte de foreach
loops no meu código para uma coisa tão simples.
java
collections
Ula Krukar
fonte
fonte
Respostas:
Com o Guava, você pode usar Lists.newArrayList (Iterable) ou Sets.newHashSet (Iterable) , entre outros métodos semelhantes. Obviamente, isso copiará todos os elementos na memória. Se isso não é aceitável, acho que seu código que funciona com estes deveria levar
Iterable
em vez deCollection
. A goiaba também fornece métodos convenientes para fazer as coisas que você pode fazerCollection
usando umIterable
(comoIterables.isEmpty(Iterable)
ouIterables.contains(Iterable, Object)
), mas as implicações de desempenho são mais óbvias.fonte
Lists.newArrayList(Iterable).clear()
Ou seja, é uma operação de tempo linear ou constante?Collection
não pode ser implementada para uma visualização deIterable
ou não será eficiente, não faz muito sentido fazer isso.Iterables.concat()
, mas que dá umaIterable
, não umCollection
:(Iterables.concat()
. A resposta muito mais longa dáCollection
... Gostaria de saber por que isso não é mais comumente suportado?No JDK 8+, sem usar nenhuma biblioteca adicional:
Edit: O acima é para
Iterator
. Se você está lidando comIterable
,fonte
iterable.forEach(target::add);
Você também pode escrever seu próprio método utilitário:
fonte
Iterable
paraCollection
é a única preocupação, prefiro essa abordagem do que importar uma grande biblioteca de coleções de terceiros.Solução concisa com Java 8 usando
java.util.stream
:fonte
IteratorUtils
partir decommons-collections
IteratorUtils.toList()
usa o iterador de uma maneira pré Java 5 para adicionar os elementos um por um a uma lista recém-criada. Simples e possivelmente mais rápido, mas adiciona 734 kB ao seu binário e você pode fazer isso sozinho se achar esse método o melhor.IteratorUtils
fromcommons-collections
pode ajudar (embora eles não suportem genéricos na versão estável mais recente 3.2.1):A versão 4.0 (que está no SNAPSHOT no momento) suporta genéricos e você pode se livrar do
@SuppressWarnings
.Atualização: Verifique
IterableAsList
no Cactoos .fonte
IterableUtils.toList(Iterable)
, que é um método de conveniência e usaIteratorUtils
sob o capô, mas também é seguro para nulos (ao contrárioIteratorUtils.toList
).Da coleçãoUtils :
Aqui estão as fontes completas deste método utilitário:
fonte
Lists.newArrayList(someIterable).clear()
Ou seja, é uma operação de tempo linear ou constante?addAll
, como o nome indica, ele copia os valores do iterador um após o outro; ele cria uma cópia em vez de uma exibição.CollectionUtils
para pular a criação da coleção em uma linha extra.Enquanto isso, não esqueça que todas as coleções são finitas, enquanto o Iterable não tem nenhuma promessa. Se algo é iterável, você pode obter um iterador e é isso.
será expandido para:
Não é necessário que it.hasNext () retorne sempre false. Portanto, no caso geral, você não pode esperar poder converter todos os iteráveis em uma coleção. Por exemplo, você pode repetir todos os números naturais positivos, repetir algo com ciclos que produzem os mesmos resultados repetidamente, etc.
Caso contrário: a resposta de Atrey é bastante boa.
fonte
Eu uso
FluentIterable.from(myIterable).toList()
muito.fonte
Esta não é uma resposta para sua pergunta, mas acredito que seja a solução para o seu problema. A interface
org.springframework.data.repository.CrudRepository
realmente possui métodos que retornam,java.lang.Iterable
mas você não deve usar essa interface. Em vez disso, use sub interfaces, no seu casoorg.springframework.data.mongodb.repository.MongoRepository
. Essa interface possui métodos que retornam objetos do tipojava.util.List
.fonte
Eu uso meu utilitário personalizado para transmitir uma coleção existente, se disponível.
A Principal:
Idealmente, o descrito acima usaria ImmutableList, mas ImmutableCollection não permite nulos que podem fornecer resultados indesejáveis.
Testes:
Eu implemento utilitários semelhantes para todos os subtipos de coleções (conjunto, lista, etc.). Eu acho que isso já faria parte da goiaba, mas não a encontrei.
fonte
Assim que você chama
contains
,containsAll
,equals
,hashCode
,remove
,retainAll
,size
outoArray
, você teria que atravessar os elementos de qualquer maneira.Se você estiver ocasionalmente chamando métodos como
isEmpty
ouclear
eu suponho que você seria melhor criando a coleção preguiçosamente. Você poderia, por exemplo, ter um apoioArrayList
para armazenar elementos iterados anteriormente.Não conheço essa classe em nenhuma biblioteca, mas deve ser um exercício bastante simples de escrever.
fonte
No Java 8, você pode fazer isso para adicionar todos os elementos de um
Iterable
paraCollection
e retorná-lo:Inspirado pela resposta @Afreys.
fonte
Como o RxJava é um martelo e isso parece um prego, você pode fazer
fonte
Aqui está um SSCCE para uma ótima maneira de fazer isso no Java 8
fonte
Me deparei com uma situação semelhante ao tentar buscar um
List
deProject
s, em vez do padrãoIterable<T> findAll()
declarado naCrudRepository
interface. Então, na minhaProjectRepository
interface (que se estende deCrudRepository
), simplesmente declarei ofindAll()
método para retornar um emList<Project>
vez deIterable<Project>
.Esta é a solução mais simples, eu acho, sem exigir lógica de conversão ou uso de bibliotecas externas.
fonte
Duas observações
fonte
Experimente
StickyList
no Cactoos :fonte
Não vi uma solução simples de uma linha sem nenhuma dependência. Eu uso simples
fonte
Você pode usar as fábricas do Eclipse Collections :
Você também pode converter
Iterable
para paraLazyIterable
e usar os métodos de conversão ou qualquer uma das outras APIs disponíveis.Todos os
Mutable
tipos acima se estendemjava.util.Collection
.Nota: Sou um colaborador das Coleções Eclipse.
fonte