根据对象属性类型从列表中提取元素

时间:2010-01-22 00:52:35

标签: java

通常,我有一个对象列表。每个对象都有属性。我想提取列表的一个子集,其中特定属性具有预定义的值。

示例:

我有一个User对象列表。用户有一个homeTown。我想从我的列表中提取所有用户,将“Springfield”作为他们的homeTown。

我通常认为这完成如下:

  

列出users = getTheUsers();

     

列表returnList = new ArrayList();

     

for(User user:users){

   if ("springfield".equalsIgnoreCase(user.getHomeTown()) 

        returnList.add(user); 
     

}

我对这个解决方案并不是特别满意。是的,它有效,但似乎很慢。必须有非线性解决方案。

建议?

5 个答案:

答案 0 :(得分:1)

嗯,这个操作本质上是线性的,除非你根据你希望以这种方式检查的属性做一些极端的事情,例如索引集合。除此之外,您只需要查看集合中的每个对象。

但是,您可以采取一些措施来提高可读性。例如,Groovy为集合提供each() method。它可以让你做这样的事情......

def returnList = new ArrayList();
users.each() {
    if ("springfield".equalsIgnoreCase(it.getHomeTown()) 
        returnList.add(user); 
};

答案 1 :(得分:1)

您需要一个自定义解决方案。创建一个自定义集合,使其实现List接口,并将原始列表中的所有元素添加到此列表中。

在此自定义List类的内部,您需要维护一些Map的所有属性集合,这些集合可以帮助您根据需要查找值。要填充此Map,您必须使用内省来查找所有字段及其值的列表。

此自定义对象必须实现一些方法List findAllBy(String propertyName, String propertyValue);,这些方法将使用上面的哈希映射来查找这些值。

这不是一个简单直接的解决方案。您还需要考虑嵌套属性,如“user.address.city”。使这个自定义列表不可变将有很大帮助。

然而,即使您在List中迭代1000个对象的列表,它仍然会更快,因此您最好根据需要迭代List。

答案 2 :(得分:0)

正如我所知,如果您使用的是列表,则必须进行迭代。无论是for-each,lambda还是FindAll - 它仍然是迭代的。不管你怎么装扮鸭子,它仍然是一只鸭子。据我所知,有HashTables,Dictionaries和DataTables不需要迭代来查找值。我不确定Java等效实现是什么,但也许这会给你一些其他想法。

答案 3 :(得分:0)

如果您对这里的表现非常感兴趣,我还建议您使用自定义解决方案。我的建议是创建一个列表树,您可以在其中对元素进行排序。

如果您对列表中元素的排序不感兴趣(大多数人通常不是这样),您也可以使用TreeMap(或HashMap)并使用homeTown作为键,并使用所有条目的List作为值。如果添加新元素,只需在Map中查找属性列表并追加它(如果它是第一个元素,您需要先创建列表)。如果要删除元素,只需执行相同的操作。

如果您想要一个具有给定homeTown的所有用户的列表,您只需要在Map中查找该列表并返回它(不需要复制所需的元素),我不是100%确定Map中的Map实现Java,但完整的方法应该是恒定的时间(最坏的情况是对数,取决于Map的实现)。

答案 4 :(得分:0)

我最终使用的是Predicates。它的可读性与Drew的建议类似。

就性能而言,我发现小型(<100项)列表的速度改进可以忽略不计。对于较大的列表(5k-10k),我发现了20-30%的改进。媒体列表有好处但不如大列表那么大。我没有测试超级大型列表,但我的测试表明,与foreach过程相比,结果看起来越大越好。

相关问题