Reputation: 1297
I have the following list of Strings:
{"New York","London","Paris","Berlin","New York"}
I am trying to use the Guava Library and I want to filter this list in such a way that I will get only the strings which will equal to a string that I will provide. If I had a fixed value let's say "New York" I would do the following:
Predicate<String> myCity = new Predicate<String>() {
@Override public boolean apply(String city) {
return city == "New York";
}
};
But what if I want the return statement to be something like this :
return city == myStringVariable
Can I give the argument for the city to the Predicate or combine two predicates somehow ?
Upvotes: 1
Views: 7318
Reputation: 11705
Guava provides a number of really generic Predicate
s, via the Predicates
helper class.
To filter on equality (be it for a String
or any other object), it provides the equalTo()
predicate:
Predicate<String> myCity = Predicates.equalTo(myStringVariable);
Update to answer a question in the comments: how to filter when the list is not of String
s but of objects which have a String
property.
You have several options, depending on what you already have:
Use imperative code
For a one-time use, unless you use Java 8, it's a bit verbose to use the functional constructs. See the FunctionalExplained page in the wiki.
private List<SomeObject> filterOnMyCity(List<SomeObject> list,
String value) {
List<SomeObject> result = new ArrayList<>();
for (SomeObject o : list) {
if (value.equals(o.getMyCity())) {
result.add(o);
}
}
return result;
}
Use an ad-hoc predicate
class MyCityPredicate implements Predicate<SomeObject> {
private final String value;
public MyCityPredicate(String value) {
this.value = value;
}
@Override
public boolean apply(@Nullable SomeObject input) {
return input != null && value.equals(input.getPropertyX());
}
}
return FluentIterable.from(list)
.filter(new MyCityPredicate(myStringVariable))
.toList();
Use an existing Function
class MyCityFunction implements Function<SomeObject, String> {
@Override
public String apply(@Nullable SomeObject input) {
return input == null ? null : input.getPropertyX();
}
}
return FluentIterable.from(list)
.filter(Predicates.compose(
Predicates.equalTo(myStringVariable),
new MyCityFunction()))
.toList();
However, I wouldn't override equals()
as mentioned in the comments, it could be too specific to say that 2 instances of SomeObject
are equals just because one of their properties is. It doesn't scale if you need to filter on 2 different properties in different contexts.
If you have Java 8, the code becomes much more compact using lambda expressions, and you can directly use the Stream
API anyway so you don't need Guava for that.
Upvotes: 8
Reputation: 720
Either you use a final String or subclass of Predicate :
final String testStr = textbox.getText(); //for example
Predicate<String> myCity = new Predicate<String>() {
@Override public boolean apply(String city) {
return city.equals(testStr);
}
};
or
public class CityPredicate implements Predicate<String>{
String cityName;
public CityPredicate(String cityName){
this.cityName = cityName;
}
@Override public boolean apply(String city) {
return city.equals(cityName);
}
}
//Use example :
Predicate<String> myCity = new CityPredicate("New York");
And as @Sotirios Delimanolis told you, always compare String with equals()
EDIT : example with Frank Pavageau's solution : Given your class :
public class City{
String cityName;
public City(String cityName){
this.cityName=cityName;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof String){
return cityName.equals(obj);
}
return false;
}
}
List<City> cities = Lists.newArrayList(new City("New York"),new City("Chicago"));
Predicate<String> myCityPredicate = Predicates.equalTo("New York");
final List<City> res = Lists.newArrayList(Iterables.filter(cities , myCityPredicate));
//res.size() will be 1 and containing only your City("New York")
//To check whether it is present you can do :
final boolean isIn = Predicates.in(cities).apply("New York");
Upvotes: 5
Reputation: 279950
You can construct the predicate by closing over a some other variable
final String cityName = "New York";
Predicate<String> myCity = new Predicate<String>() {
@Override public boolean apply(String city) {
return city.equals(cityName);
}
};
Note how I compare strings with their equals
method rather than the ==
reference equality operator. See below for why.
How do I compare strings in Java?
Upvotes: 2