Eu quero filtrar um com java.util.Collection
base em um predicado.
java
collections
filter
Kevin Wong
fonte
fonte
persons.removeIf(p -> p.getAge() <= 16);
Supondo que você esteja usando Java 1.5 e que não possa adicionar o Google Collections , eu faria algo muito semelhante ao que os caras do Google fizeram. Essa é uma pequena variação nos comentários de Jon.
Primeiro adicione essa interface à sua base de código.
Seus implementadores podem responder quando um determinado predicado é verdadeiro para um determinado tipo. Por exemplo, se
T
wereUser
eAuthorizedUserPredicate<User>
implementaIPredicate<T>
, entãoAuthorizedUserPredicate#apply
retorna se a passagemUser
é autorizada.Então, em alguma classe de utilidade, você poderia dizer
Portanto, supondo que você tenha o uso do acima exposto pode ser
Se o desempenho na verificação linear é motivo de preocupação, talvez eu queira ter um objeto de domínio que tenha a coleção de destino. O objeto de domínio que possui a coleção de destino teria lógica de filtragem para os métodos que inicializam, adicionam e definem a coleção de destino.
ATUALIZAR:
Na classe de utilitário (digamos Predicate), adicionei um método select com uma opção para o valor padrão quando o predicado não retorna o valor esperado, e também uma propriedade estática para os parâmetros serem usados dentro do novo IPredicate.
O exemplo a seguir procura objetos ausentes entre coleções:
O exemplo a seguir procura uma instância em uma coleção e retorna o primeiro elemento da coleção como valor padrão quando a instância não é encontrada:
UPDATE (após o lançamento do Java 8):
Faz vários anos desde que eu (Alan) publiquei esta resposta pela primeira vez, e ainda não consigo acreditar que estou coletando pontos SO para esta resposta. De qualquer forma, agora que o Java 8 introduziu fechamentos para a linguagem, minha resposta agora seria consideravelmente diferente e mais simples. Com o Java 8, não há necessidade de uma classe de utilitário estático distinta. Portanto, se você deseja encontrar o primeiro elemento que corresponde ao seu predicado.
O JDK 8 API para opcionais tem a capacidade de
get()
,isPresent()
,orElse(defaultUser)
,orElseGet(userSupplier)
eorElseThrow(exceptionSupplier)
, bem como outras funções 'monádicos' tais comomap
,flatMap
efilter
.Se você deseja simplesmente coletar todos os usuários que correspondem ao predicado, use o
Collectors
para finalizar o fluxo na coleção desejada.Veja aqui para mais exemplos de como o Java 8 streams funciona.
fonte
val authorized = for (user <- users if user.isAuthorized) yield user
Use CollectionUtils.filter (Collection, Predicate) , do Apache Commons.
fonte
A "melhor" maneira é uma solicitação muito ampla. É o "mais curto"? "O mais rápido"? "Legível"? Filtrar no local ou em outra coleção?
A maneira mais simples (mas não a mais legível) é iterá-la e usar o método Iterator.remove ():
Agora, para torná-lo mais legível, você pode agrupá-lo em um método utilitário. Em seguida, invente uma interface IPredicate, crie uma implementação anônima dessa interface e faça algo como:
em que filterInPlace () itera a coleção e chama Predicate.keepIt () para saber se a instância deve ser mantida na coleção.
Realmente não vejo uma justificativa para trazer uma biblioteca de terceiros apenas para esta tarefa.
fonte
stream()
recurso, mas nem todo mundo brinca com os brinquedos mais novos: PConsidere o Google Collections para obter uma estrutura de coleções atualizada que ofereça suporte a genéricos.
ATUALIZAÇÃO : a biblioteca de coleções do Google agora está obsoleta. Você deve usar a versão mais recente do Guava . Ele ainda possui as mesmas extensões da estrutura de coleções, incluindo um mecanismo de filtragem com base em um predicado.
fonte
Aguarde o Java 8:
fonte
personList.removeIf(p -> p.age < 30);
Menos detalhado. Além disso, ouvi falar sobre começar a implementar APIs que aceitam e retornamStream
s, em vez deCollection
s, porqueStream
s são muito úteis e rápidos, mas é muito lento ir / voltar deles.Desde o lançamento inicial do Java 8, você pode tentar algo como:
Por exemplo, se você tivesse uma lista de números inteiros e desejasse filtrar os números> 10 e depois imprimir esses números no console, você poderia fazer algo como:
fonte
Vou jogar RxJava no ringue, que também está disponível no Android . O RxJava nem sempre é a melhor opção, mas oferece mais flexibilidade se você deseja adicionar mais transformações à sua coleção ou manipular erros durante a filtragem.
Resultado:
Mais detalhes sobre o RxJava
filter
podem ser encontrados aqui .fonte
A configuração:
O uso:
fonte
Que tal um Java simples e direto
Simples, legível e fácil (e funciona no Android!) Mas se você estiver usando o Java 8, poderá fazê-lo em uma linha agradável:
Observe que toList () é importado estaticamente
fonte
Tem certeza de que deseja filtrar a própria coleção, em vez de um iterador?
consulte org.apache.commons.collections.iterators.FilterIterator
ou usando a versão 4 do apache commons org.apache.commons.collections4.iterators.FilterIterator
fonte
Vejamos como filtrar uma lista JDK integrada e uma MutableList usando Eclipse Collections .
Se você deseja filtrar os números com menos de 3, esperaria as seguintes saídas.
Veja como você pode filtrar usando um Java 8 lambda como o
Predicate
.Veja como você pode filtrar usando uma classe interna anônima como o
Predicate
.Aqui estão algumas alternativas para filtrar listas JDK e listas mutáveis de coleções do Eclipse usando a fábrica de Predicados .
Aqui está uma versão que não aloca um objeto para o predicado, usando a fábrica Predicates2 em vez disso com o
selectWith
método que leva aPredicate2
.Às vezes, você deseja filtrar uma condição negativa. Existe um método especial no Eclipse Collections para esse chamado
reject
.O método
partition
retornará duas coleções, contendo os elementos selecionados e rejeitados peloPredicate
.Nota: Sou um colaborador das Coleções Eclipse.
fonte
removeIf
em uma lista ou em um conjunto de primitivas?Com o ForEach DSL, você pode escrever
Dada uma coleção de [The, quick, brown, fox, saltos, over, the, preguiçoso, cachorro], isso resulta em [quick, brown, saltos, over, preguiçoso], ou seja, todas as strings com mais de três caracteres.
Todos os estilos de iteração suportados pelo ForEach DSL são
AllSatisfy
AnySatisfy
Collect
Counnt
CutPieces
Detect
GroupedBy
IndexOf
InjectInto
Reject
Select
Para mais detalhes, consulte https://www.iam.unibe.ch/scg/svn_repos/Sources/ForEach
fonte
O método Collections2.filter (Collection, Predicate) na biblioteca Guava do Google faz exatamente o que você está procurando.
fonte
Como o java 9
Collectors.filtering
está ativado:Assim, a filtragem deve ser:
Exemplo:
fonte
Isso, combinado com a falta de fechamentos reais, é minha maior reclamação pelo Java. Honestamente, a maioria dos métodos mencionados acima é muito fácil de ler e REALMENTE eficiente; no entanto, depois de passar um tempo com .Net, Erlang, etc ..., a compreensão da lista integrada no nível do idioma torna tudo muito mais limpo. Sem acréscimos no nível da linguagem, o Java simplesmente não pode ser tão limpo quanto muitas outras linguagens nesta área.
Se o desempenho é uma grande preocupação, as coleções do Google são o caminho a seguir (ou escreva seu próprio utilitário de predicado simples). A sintaxe do Lambdaj é mais legível para algumas pessoas, mas não é tão eficiente.
E depois há uma biblioteca que escrevi. Ignorarei qualquer dúvida em relação à sua eficiência (sim, é tão ruim) ...... Sim, eu sei que é claramente baseado em reflexão, e não, na verdade não o uso, mas funciona:
OU
fonte
O JFilter http://code.google.com/p/jfilter/ é mais adequado para suas necessidades.
O JFilter é uma biblioteca de código aberto simples e de alto desempenho para consultar a coleção de Java beans.
Características principais
fonte
Eu escrevi uma classe Iterable estendida que suporta a aplicação de algoritmos funcionais sem copiar o conteúdo da coleção.
Uso:
O código acima realmente executará
fonte
Use o mecanismo de consulta de coleção (CQEngine) . É de longe a maneira mais rápida de fazer isso.
Consulte também: Como você consulta coleções de objetos em Java (como Critérios / SQL)?
fonte
Algumas ótimas ótimas respostas aqui. Eu, gostaria de manter o mais simples e legível possível:
fonte
A solução simples pré-Java8:
Infelizmente, essa solução não é totalmente genérica, produzindo uma lista em vez do tipo da coleção fornecida. Além disso, trazer bibliotecas ou funções de escrita que envolvem esse código parece um exagero para mim, a menos que a condição seja complexa, mas você pode escrever uma função para a condição.
fonte
https://code.google.com/p/joquery/
Suporta diferentes possibilidades,
Dada a coleção,
do tipo
Filtro
Java 7
Java 8
Além disso,
Classificação (também disponível para o Java 7)
Agrupamento (também disponível para o Java 7)
Junções (também disponíveis para o Java 7)
Dado,
Pode ser juntado como,
Expressões
fonte
Minha resposta baseia-se que a partir de Kevin Wong, aqui como uma one-liner usando
CollectionUtils
de primavera e uma Java 8 lambda expressão.Isso é tão conciso e legível quanto qualquer alternativa que eu tenha visto (sem usar bibliotecas baseadas em aspectos)
O Spring CollectionUtils está disponível na versão 4.0.2.RELEASE da primavera e lembre-se de que você precisa do JDK 1.8 e do nível de idioma 8+.
fonte
Usando
java 8
, especificamentelambda expression
, você pode fazê-lo simplesmente como no exemplo abaixo:onde, para cada coleção
product
internamyProducts
,prod.price>10
adicione este produto à nova lista filtrada.fonte
Eu precisava filtrar uma lista, dependendo dos valores já presentes na lista. Por exemplo, remova todos os valores seguintes que sejam menores que o valor atual. {2 5 3 4 7 5} -> {2 5 7}. Ou, por exemplo, para remover todas as duplicatas {3 5 4 2 3 5 6} -> {3 5 4 2 6}.
Isso será usado assim.
fonte
Com goiaba:
fonte
No Java 8, você pode usar diretamente esse método de filtro e, em seguida, fazer isso.
fonte