【问题标题】:how to implement search on property in list (Collection)如何在列表(集合)中实现对属性的搜索
【发布时间】:2013-10-02 11:13:58
【问题描述】:

我想对列表中的对象的属性进行搜索。

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
}
}
}

【问题讨论】:

  • 首先使用普通的旧循环编写搜索。然后研究你写的内容,找出比较器的组成部分。
  • 您能详细说明一下吗?你的意思是循环列表并根据属性比较搜索值。是吗?
  • 所以你知道需要使用Comparator,但不知道如何使用?你为什么不学习?
  • 因为是三个字段,所以不能简单的使用binarySearch。要使用binarySearch,必须对列表进行排序。您不能对三个字段的列表进行排序。
  • 我编辑了我的代码。这是正确的方法吗?这只是一个示例,实际上我在 bean 中有 25 个属性。

标签: java list search comparator


【解决方案1】:

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

我能想到的是:java反射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)

还有来自番石榴的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)

【讨论】:

    【解决方案2】:

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

    我使用 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. 您希望属性具有的值

    为了在 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");
    }
    

    【讨论】:

    • OP 有一大块“如果此属性,则调用 getThisProperty() 否则如果该属性...”您的方法只是将此块移动到 bean 类中,对吗?如果这样做,Map&lt;String, Object&gt; 就足够了。例如PropertyMap&lt;String, Object&gt; map 然后map.put("name",this.name);.....
    • 好的,但是使用这种方法,您不必为每个对象创建地图,只是为了搜索。如果有许多具有不同属性的类,我宁愿使用反射。或者使用 Lambdaj 之类的东西。
    • 地图将在 bean 类中。我写了这个名字
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多