如何在列表中的属性上实现搜索(Collection)

时间:2013-10-02 11:13:58

标签: java list search comparator

我想在列表中的对象的属性上实现搜索。

class Test
{
    int id;
    int name;
    int address;

    //Setter and getter method of properties
}

public List<Test> searchData(String serachText, String propertyName)
{
    //Write code to search data from list
}

输入参数:

searchData("val1", "name");
searchData("val2", ("address");

我想使用Collections.binarySearch,但如何进行dynamic comparator搜索,我不知道。

实现这种功能的正确方法是什么?

是否可以使用Collections.binarySearch或任何其他良好的方式实现它,并且具有更好的性能的高质量代码?

修改

public List<Test> searchData(String serachText, String propertyName)
{
List<Test> finalSearch=new ArrayList<Test>();
//Write code to search data
for(Test test:testList)
{
  if(propertyName.equals("name"))
{
    if(serachText.equals(test.getName())
    {
       finalSearch.add(test);
     }
///Same code for others
}
}
}

2 个答案:

答案 0 :(得分:0)

我怀疑你可以用这个问题进行bin搜索。如果要进行二进制搜索,则必须按给定的propertyName对集合中的元素进行排序。如果不是,则必须先对其进行排序(例如,使用比较器)。因此,您要将O(n)问题更改为O(nlgn)

我能想到的是:java reflection API ....也就是说,在你的searchData方法中,用给定的属性名构建getter方法(java.lang.reflect.Method)。并调用(method.invoke() http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,java.lang.Object ...))来获取属性值。并进行过滤。

你可以自己实现它,如果你不介意使用库,你可以看看apache beanUtils:(getProperty()方法)

http://commons.apache.org/proper/commons-beanutils/javadocs/v1.8.3/apidocs/org/apache/commons/beanutils/PropertyUtilsBean.html#getProperty(java.lang.Object,java.lang.String)

来自guava的Iterables.filter()方法:

http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#filter(java.lang.Iterable,com.google.common.base.Predicate)

答案 1 :(得分:0)

正如其他人所说,如果不先对列表进行排序,就不能使用二进制搜索,所以我不会考虑到这一点。

使用Google的Guava libraries我可以很好地解决这个问题而不需要反思。

public static <T, V> Collection<T> filter(List<T> source, final Function<? super T, V> function, final V value) {
    return Collections2.filter(source, new Predicate<T>() {
        @Override
        public boolean apply(T input) {
            return value.equals(function.apply(input));
        }
    });
}

此功能有三个参数。

  1. 您要过滤的列表。
  2. 一个函数,它接受列表的元素,并返回要在
  3. 上过滤的属性的值
  4. 您希望物业拥有的价值
  5. 为了在Java 8之前使用它,您可以编写如下内容:

    static class Test {
        int id;
        String name;
        String address;
    
        public Test(int id, String name, String address) {
            this.id = id;
            this.name = name;
            this.address = address;
        }
    
        //Setter and getter method of properties...
    
        public static final Function<Test, Integer> GetId = new Function<Test, Integer>() {
            @Override
            public Integer apply(Test input) {
                return input.id;
            }
        };
        public static final Function<Test, String> GetName = new Function<Test, String>() {
            @Override
            public String apply(Test input) {
                return input.name;
            }
        };
    
    }
    

    定义Test.GetIdTest.GetName等后,使用filter很简单明了:

    public static void main(String[] args) {
        List<Test> t = Arrays.asList(new Test(1, "A", "B"), new Test(2, "C", "D"));
        Collection<Test> f1 = filter(t, Test.GetId, 2);
        Collection<Test> f2 = filter(t, Test.GetName, "A");
    }