我有几个需要按不同标准搜索的列表类(单个值,多个值等)。目前,这些类根据搜索条件具有不同的方法。因为我不想一次又一次地编写相同的代码,所以我希望避免这种情况...但我不想重新发明轮子。 所以,我正在考虑创建一个实现通用搜索的自定义类。
代码如下所示:
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。
答案 0 :(得分:3)
我正在重新发明轮子,因为它已经完成了?或者可以吗?
是的,你正在重新发明轮子。 你所建议的几乎完全匹配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);
}
}
Predicate是一个通用接口,它指定一个方法,如果某些内容匹配或没有给出该值,则返回一个布尔值。
如何定义谓词的示例:
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版本,你可以使用例如guava 2,它也拥有它自己的Predicate 3系统。
然后,您可以使用Iterables 4类对其进行过滤,最后使用5将其收回到列表中。
你当然可以找到一个替代方案或自己创建一个函数来组合filter + collect到list方法。
您还可以使用谓词类6组合谓词,并使用它们构建某些简单谓词。
这是使用番石榴的完整示例。
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);
}
}
您可以使用要排序的类中的函数定义谓词,并将它们与可用于检查值是否与某个目标匹配的其他类组合。
e.g。
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.