Java按不同标准搜索条件
问题描述:
我有几个列表类,需要按不同的标准(单个值,多个值等)搜索。目前,这些类具有取决于搜索标准的不同方法。由于我讨厌一次又一次地写相同的代码,我正在寻求避免这一点...但我不想重新发明*。 所以,我正在考虑创建一个自定义的类,实现一个通用的搜索。Java按不同标准搜索条件
的代码看起来是这样的:
import java.util.ArrayList;
import java.util.Iterator;
public class ListCustomComparable<T> {
private ArrayList<T> listItems;
public ListCustomComparable() {
}
/**
* @return the listItems
*/
public ArrayList<T> getListItems() {
return listItems;
}
/**
* @param listItems the listItems to set
*/
public void setListItems(ArrayList<T> listItems) {
this.listItems = listItems;
}
public ArrayList<T> searchByComparable(Comparable<T> comparator){
ArrayList<T> listRes= new ArrayList<T>();
for (T item: listItems){
if(comparator.equals(item))
listRes.add(item);
}
return listRes;
}
}
于是,我假装每一个想要做一个特定的搜索方法必须实现媲美接口。显然,这种方法需要自己的代码,但是会依赖泛型类。 请问,您对此有何看法?我正在重新发明*,因为它已经完成了?还是可以吗?
另外一个限制。它应该与1.6一起工作。
答
我正在重新发明*,因为它已经完成了吗?还是可以吗?
是的,你正在重新发明*。 你的建议几乎完全匹配Predicates。
下面是一个例子:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Example {
static class Person{
int age;
String name;
Person(int age, String name){
this.age = age;
this.name = name;
}
}
public static void main(String[] args){
List<Person> persons = new ArrayList<>();
persons.add(new Person(20,"John"));
persons.add(new Person(25,"Alice"));
persons.add(new Person(30,"Peter"));
persons.add(new Person(25,"Stefan"));
List<Person> results = persons.stream()
.filter(p -> p.age <= 25 && p.name.equals("Stefan"))
.collect(Collectors.toList());
for(Person p : results)
System.out.println(p.name);
}
}
谓词是一个通用的接口来指定,如果事情匹配或不给予该值返回boolean值的方法。如何谓词
例子可以定义:
Predicate<String> filter_1 = str -> "value".equals(str);
Predicate<String> filter_2 = "value"::equals;
Predicate<String> filter_3 = new Predicate<String>() {
@Override
public boolean test(String s) {
return "value".equals(s);
}
};
Predicate<String> minLengthFilter = str -> str != null && str.length() > 5;
Predicate<String> maxLengthFilter = str -> str != null && str.length() < 8;
Predicate<String> combined = minLengthFilter.and(maxLengthFilter);
如果你有1.8前用Java版本的工作,你可以使用例如番石榴2也有它自己的谓词3系统。
然后,您可以使用应用程序4类对其进行过滤,最后使用5将其收集回列表中。
你当然可以找到一个替代方案或使自己的功能,结合过滤器+收集到列表方法。
您还可以使用它们的谓词类6组合Predicates,并且可以使用它们构造某些简单的谓词。
下面是一个使用番石榴的完整例子。
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.List;
public class GuavaExample {
static class Person{
int age;
String name;
boolean isFemale;
Person(int age, String name, boolean isFemale){
this.age = age;
this.name = name;
this.isFemale = isFemale;
}
}
public static <T> List<T> applyFilter(List<? extends T> list, Predicate<? super T> ... filters){
// default case: no filters.
if (filters == null || filters.length == 0)
return new ArrayList<T>(list);
Iterable<? extends T> it = Iterables.filter(list,Predicates.and(filters));
return Lists.newArrayList(it);
}
public static <T> List<T> applyFilter(List<? extends T> list, Predicate<? super T> filter){
Iterable<? extends T> it = Iterables.filter(list,filter);
return Lists.newArrayList(it);
}
public static void main(String[] args) {
List<Person> result;
List<Person> persons = new ArrayList<Person>();
persons.add(new Person(8, "Little John",false));
persons.add(new Person(10, "Alice Jnr.",true));
persons.add(new Person(20,"John",false));
persons.add(new Person(25,"Alice",true));
persons.add(new Person(30,"Sarah",true));
persons.add(new Person(25,"Stefan",false));
Predicate<Person> isAdult = new Predicate<Person>() {
@Override
public boolean apply(Person person) {
return person.age >= 18;
}
};
Predicate<Person> isFemale = new Predicate<Person>() {
@Override
public boolean apply(Person person) {
return person.isFemale;
}
};
result = applyFilter(persons,isAdult);
System.out.println("Adults: ");
for(Person p : result)
System.out.println(p.name);
result = applyFilter(persons,Predicates.not(isAdult));
System.out.println("Children: ");
for(Person p : result)
System.out.println(p.name);
// Generic varargs will yield a warning, unfortionally...
result = applyFilter(persons, isAdult, isFemale);
System.out.println("Adult females: ");
for(Person p : result)
System.out.println(p.name);
}
}
也许你可以定义使用要进行排序,并与可用于检查一个值有一定客观匹配其他类将它们组合起来的类中的功能谓语。
例如
static class Person {
int age;
// ... code ...
public static Predicate<Person> ageFilter(final Range<Integer> range) {
return new Predicate<Person>() {
@Override
public boolean apply(Person person) {
return range.contains(person.age);
}
};
}
}
然后可以重新用于各种过滤器:
Predicate<Person> isAdult = Person.ageFilter(Range.atLeast(18)); // Yields 18 and older.
Predicate<Person> isToddler = Person.ageFilter(Range.open(1,3)); // Yields ages 1-3, including 1 and 3 exact.
Predicate<Person> isMiddleAge = Person.ageFilter(Range.openClosed(45,65)); // Yields ages 45-65, 45 included, 65 excluded.
太谢谢你了。它看起来很完美。我没有说的是我需要使用Java 1.6,我认为lamba表达式至少需要1.8。 – drusilabs
Updated :) - 查看关于番石榴的新部分/部分。 – user254948