I want to filter a java.util.Collection
based on a predicate.
相关问题
- Delete Messages from a Topic in Apache Kafka
- Jackson Deserialization not calling deserialize on
- How to maintain order of key-value in DataFrame sa
- StackExchange API - Deserialize Date in JSON Respo
- Difference between Types.INTEGER and Types.NULL in
Java 8 (2014) solves this problem using streams and lambdas in one line of code:
Here's a tutorial.
Use
Collection#removeIf
to modify the collection in place. (Notice: In this case, the predicate will remove objects who satisfy the predicate):lambdaj allows filtering collections without writing loops or inner classes:
Can you imagine something more readable?
Disclaimer: I am a contributor on lambdaj
Wait for Java 8:
I'll throw RxJava in the ring, which is also available on Android. RxJava might not always be the best option, but it will give you more flexibility if you wish add more transformations on your collection or handle errors while filtering.
Output:
More details on RxJava's
filter
can be found here.Using
java 8
, specificallylambda expression
, you can do it simply like the below example:where for each
product
insidemyProducts
collection, ifprod.price>10
, then add this product to the new filtered list.Assuming that you are using Java 1.5, and that you cannot add Google Collections, I would do something very similar to what the Google guys did. This is a slight variation on Jon's comments.
First add this interface to your codebase.
Its implementers can answer when a certain predicate is true of a certain type. E.g. If
T
wereUser
andAuthorizedUserPredicate<User>
implementsIPredicate<T>
, thenAuthorizedUserPredicate#apply
returns whether the passed inUser
is authorized.Then in some utility class, you could say
So, assuming that you have the use of the above might be
If performance on the linear check is of concern, then I might want to have a domain object that has the target collection. The domain object that has the target collection would have filtering logic for the methods that initialize, add and set the target collection.
UPDATE:
In the utility class (let's say Predicate), I have added a select method with an option for default value when the predicate doesn't return the expected value, and also a static property for params to be used inside the new IPredicate.
The following example looks for missing objects between collections:
The following example, looks for an instance in a collection, and returns the first element of the collection as default value when the instance is not found:
UPDATE (after Java 8 release):
It's been several years since I (Alan) first posted this answer, and I still cannot believe I am collecting SO points for this answer. At any rate, now that Java 8 has introduced closures to the language, my answer would now be considerably different, and simpler. With Java 8, there is no need for a distinct static utility class. So if you want to find the 1st element that matches your predicate.
The JDK 8 API for optionals has the ability to
get()
,isPresent()
,orElse(defaultUser)
,orElseGet(userSupplier)
andorElseThrow(exceptionSupplier)
, as well as other 'monadic' functions such asmap
,flatMap
andfilter
.If you want to simply collect all the users which match the predicate, then use the
Collectors
to terminate the stream in the desired collection.See here for more examples on how Java 8 streams work.
This, combined with the lack of real closures, is my biggest gripe for Java. Honestly, most of the methods mentioned above are pretty easy to read and REALLY efficient; however, after spending time with .Net, Erlang, etc... list comprehension integrated at the language level makes everything so much cleaner. Without additions at the language level, Java just cant be as clean as many other languages in this area.
If performance is a huge concern, Google collections is the way to go (or write your own simple predicate utility). Lambdaj syntax is more readable for some people, but it is not quite as efficient.
And then there is a library I wrote. I will ignore any questions in regard to its efficiency (yea, its that bad)...... Yes, i know its clearly reflection based, and no I don't actually use it, but it does work:
OR