代码之家  ›  专栏  ›  技术社区  ›  DDus

基于对象属性类型从列表中提取元素

  •  3
  • DDus  · 技术社区  · 16 年前

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

    例子:

    我有一个用户对象列表。用户有家乡。我想从我的列表中提取所有以“SpringField”为家乡的用户。

    我通常认为这项工作完成如下:

    list users=gettheusers();

    list returnlist=new arraylist();

    对于(用户用户:用户){

       if ("springfield".equalsIgnoreCase(user.getHomeTown()) 
    
            returnList.add(user); 
    

    }

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

    建议?

    5 回复  |  直到 14 年前
        1
  •  1
  •   Drew Wills    16 年前

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

    但是,您可以做一些事情来提高可读性。例如,groovy提供了 each() method 收藏。它会让你做这样的事情…

    def returnList = new ArrayList();
    users.each() {
        if ("springfield".equalsIgnoreCase(it.getHomeTown()) 
            returnList.add(user); 
    };
    
        2
  •  1
  •   Gladwin Burboz    16 年前

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

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

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

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

    但是,即使您正在迭代列表中1000个对象的列表,它仍然会更快,所以最好不要迭代列表以满足您的需要。

        3
  •  0
  •   IAbstract    16 年前

    正如我发现的那样,如果您使用的是列表,那么必须迭代。无论是它的a for each、lambda还是findall——它仍在迭代。不管你怎么打扮鸭子,它还是一只鸭子。据我所知,有些哈希表、字典和数据表不需要迭代来查找值。我不确定Java等价的实现是什么,但也许这会给你一些其他的想法。

        4
  •  0
  •   Nils Schmidt    16 年前

    如果你真的对这里的表演感兴趣,我也建议你 自定义解决方案 .我的建议是 列表树 在其中可以对元素进行排序。

    如果您对列表中元素的顺序不感兴趣(大多数人通常不感兴趣),您还可以使用treemap(或hashmap)并使用home作为键,使用所有条目的列表作为值。如果添加了新元素,只需在地图中查找归属列表并附加它(如果它是第一个元素,当然您需要首先创建列表)。如果您想删除一个元素,只需执行相同的操作。

    在你想要一个给定的家乡的所有用户的列表中,你只需要在地图中查找该列表并返回它(不需要复制所需的元素),我对Java中的地图实现不确定100%,但是完整的方法应该是在固定的时间(最坏情况下的对数,这取决于地图实现)。

        5
  •  0
  •   DDus    14 年前

    最后我使用了谓词。它的可读性与德鲁的建议类似。

    就性能而言,我发现小的(100项)列表的速度改进微不足道。对于更大的列表(5公里到10公里),我发现有20%到30%的改进。中等名单有好处,但不如大名单大。我没有测试超大的列表,但是我的测试使列表看起来很大,与foreach过程相比,结果更好。