Java搜索列表按不同标准

时间:2016-06-10 08:35:42

标签: java generics search arraylist

我有几个需要按不同标准搜索的列表类(单个值,多个值等)。目前,这些类根据搜索条件具有不同的方法。因为我不想一次又一次地编写相同的代码,所以我希望避免这种情况...但我不想重新发明轮子。 所以,我正在考虑创建一个实现通用搜索的自定义类。

代码如下所示:

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。

1 个答案:

答案 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.