Existe uma razão para isso
Lists.transform()
mas não
Lists.filter()
?
Como posso filtrar uma lista corretamente? eu poderia usar
new ArrayList(Collection2.filter())
claro, mas assim não é garantido que a minha encomenda continue a mesma, se bem entendi.
List.newArrayList(Iterables.filter(...))
, deveria dizerLists.newArrayList(Iterables.filter(...))
.Respostas:
Não foi implementado porque exporia um grande número perigoso de métodos lentos, como #get (index) na exibição de Lista retornada (convidando bugs de desempenho). E ListIterator também seria difícil de implementar (embora eu tenha enviado um patch anos atrás para cobrir isso).
Como os métodos indexados não podem ser eficientes na visualização de Lista filtrada, é melhor apenas ir com um Iterable filtrado, que não os tem.
fonte
filter
significa consistentemente uma visão (junto com o comportamento que implica) seja issoIterables.filter
,Sets.filter
etc. Uma vez queIterables.filter
combina facilmente comcopyOf
em qualquerImmutableCollection
, considero esta uma boa compensação de design (versus surgindo com métodos e nomes extras, comofilteredCopy
ou outros enfeites , para combinações de utilitários simples).Você pode usar
Iterables.filter
, o que definitivamente manterá os pedidos.Observe que, ao construir uma nova lista, você estará copiando os elementos (apenas referências, é claro) - portanto, não será uma exibição ao vivo na lista original. Criar uma visualização seria bem complicado - considere esta situação:
Predicate<StringBuilder> predicate = /* predicate returning whether the builder is empty */ List<StringBuilder> builders = Lists.newArrayList(); List<StringBuilder> view = Lists.filter(builders, predicate); for (int i = 0; i < 10000; i++) { builders.add(new StringBuilder()); } builders.get(8000).append("bar"); StringBuilder firstNonEmpty = view.get(0);
Isso teria que iterar por toda a lista original, aplicando o filtro a tudo. Suponho que isso possa exigir que a correspondência de predicado não mude ao longo do tempo de vida da visualização, mas isso não seria inteiramente satisfatório.
(Isso é apenas adivinhação, veja bem. Talvez um dos mantenedores do Guava venha a contribuir com o verdadeiro motivo :)
fonte
Collections2.filter.iterator
apenas chamaIterables.filter
, então o resultado é o mesmo.Iterables.filter
versão apenas para maior clareza.view.size()
lugar posterior no código :)Isso não é verdade.
Collections2.filter()
é uma função avaliada vagarosamente - ela não filtra realmente sua coleção até que você comece a acessar a versão filtrada. Por exemplo, se você iterar sobre a versão filtrada, os elementos filtrados sairão do iterador na mesma ordem que sua coleção original (menos os filtrados, obviamente).Talvez você estivesse pensando que ele faz a filtragem antecipadamente e, em seguida, despeja os resultados em uma coleção arbitrária e não ordenada de alguma forma - não faz.
Portanto, se você usar a saída de
Collections2.filter()
como entrada para uma nova lista, seu pedido original será mantido.Usando importações estáticas (e a
Lists.newArrayList
função), torna-se bastante sucinto:Observe que, embora
Collections2.filter
não vá iterar avidamente sobre a coleção subjacente,Lists.newArrayList
irá - ele irá extrair todos os elementos da coleção filtrada e copiá-los em uma novaArrayList
.fonte
List filteredList = newArrayList(filter(originalList, new Predicate<T>() { @Override public boolean apply(T input) { return (...); } }));
ou ie.List filteredList = newArrayList(filter(originalList, Predicates.notNull()));
Conforme mencionado por Jon, você pode usar
Iterables.filter(..)
ouCollections2.filter(..)
e se não precisar de uma visualização ao vivo, você pode usarImmutableList.copyOf(Iterables.filter(..))
ouLists.newArrayList( Iterables.filter(..))
e sim, o pedido será mantido.Se você estiver realmente interessado em saber por que parte, você pode visitar https://github.com/google/guava/issues/505 para obter mais detalhes.
fonte
Resumindo o que os outros disseram, você pode criar facilmente um wrapper genérico para filtrar listas:
public static <T> List<T> filter(Iterable<T> userLists, Predicate<T> predicate) { return Lists.newArrayList(Iterables.filter(userLists, predicate)); }
fonte