首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Java中查询对象集合(Criteria/SQL-like)?

如何在Java中查询对象集合(Criteria/SQL-like)?
EN

Stack Overflow用户
提问于 2008-09-18 15:08:49
回答 7查看 35.4K关注 0票数 32

假设您有一个由数百个内存中对象组成的集合,您需要查询此列表以返回与某些SQL或查询之类的条件匹配的对象。例如,您可能有一个汽车对象列表,并且希望返回20世纪60年代生产的所有汽车,车牌以AZ开头,按汽车型号的名称排序。

我知道JoSQL,有没有人用过它,或者对其他/自主开发的解决方案有任何经验?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2008-09-18 15:29:50

我在一个生产应用程序中使用过Apache Commons JXPath。它允许您将XPath表达式应用于Java语言中的对象图。

票数 13
EN

Stack Overflow用户

发布于 2012-07-30 05:02:32

过滤是实现此目的的一种方法,正如在其他答案中所讨论的。

不过,过滤是不可伸缩的。从表面上看,时间复杂度似乎是O(n) (即,如果集合中的对象数量将增长,则时间复杂度已经不可扩展),但实际上,因为需要根据查询对每个对象应用一个或多个测试,所以时间复杂度更准确地是O(n,t),其中t是应用于每个对象的测试数量。

因此,随着其他对象被添加到集合中,和/或随着查询中测试数量的增加,性能将会降低。

还有另一种方法可以做到这一点,使用索引和集合论。

一种方法是在存储在集合中的对象内的字段上构建索引,您随后将在查询中对其进行测试。

假设您有一个Car对象集合,并且每个Car对象都有一个字段color。假设您的查询等同于"SELECT * FROM cars WHERE Car.color = 'blue'“。您可以在Car.color上构建一个索引,它基本上如下所示:

代码语言:javascript
复制
'blue' -> {Car{name=blue_car_1, color='blue'}, Car{name=blue_car_2, color='blue'}}
'red'  -> {Car{name=red_car_1, color='red'}, Car{name=red_car_2, color='red'}}

然后,给定一个查询WHERE Car.color = 'blue',可以在O(1)时间复杂度内检索到蓝色汽车集。如果查询中还有其他测试,则可以测试候选集中的每辆车,以检查它是否与查询中的其余测试匹配。由于候选集合可能比整个集合小得多,因此时间复杂度小于O(n) (在工程意义上,请参阅下面的注释)。当将其他对象添加到集合中时,性能不会降低很多。但这仍然不是完美的,请继续阅读。

另一种方法是我所说的标准查询索引。解释一下:使用传统的迭代和过滤,将迭代集合,并测试每个对象以查看它是否与查询匹配。因此,过滤就像在集合上运行查询一样。标准查询索引将是另一种方式,集合在查询上运行,但对于集合中的每个对象只运行一次,即使集合可以被查询任意次。

标准查询索引将类似于向某种类型的智能集合注册查询,从而当向集合添加对象和从集合中移除对象时,集合将针对已向其注册的所有标准查询自动测试每个对象。如果一个对象匹配一个标准查询,那么集合可以将它添加到/从专用于存储匹配该查询的对象的集合中删除。随后,匹配任何注册查询的对象可以在O(1)时间复杂度内被检索到。

以上信息取自CQEngine (Collection Query Engine)。这基本上是一个NoSQL查询引擎,用于使用类似SQL的查询从Java集合中检索对象,而不会产生迭代集合的开销。它是围绕上面的想法构建的,还有更多的想法。免责声明:我是作者。它是开源的,位于maven central。如果你觉得这对你有帮助,请给这个答案加分!

票数 26
EN

Stack Overflow用户

发布于 2014-03-07 00:52:59

是的,我知道这是一个古老的帖子,但技术每天都会出现,答案会随着时间的推移而改变。

我认为这是一个用LambdaJ解决它的好问题。你可以在这里找到它:http://code.google.com/p/lambdaj/

下面是一个示例:

查找活跃客户// (可选版本)

代码语言:javascript
复制
List<Customer> activeCustomers = new ArrayList<Customer>();  
for (Customer customer : customers) {  
  if (customer.isActive()) {  
    activeCusomers.add(customer);  
  }  
}  

LambdaJ版本

代码语言:javascript
复制
List<Customer> activeCustomers = select(customers, 
                                        having(on(Customer.class).isActive()));  

当然,拥有这样的美感会对表演产生影响(有点...平均2次),但是你能找到可读性更好的代码吗?

它有很多很多的功能,另一个例子是排序:

排序迭代

代码语言:javascript
复制
List<Person> sortedByAgePersons = new ArrayList<Person>(persons);
Collections.sort(sortedByAgePersons, new Comparator<Person>() {
        public int compare(Person p1, Person p2) {
           return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
        }
}); 

使用λ的排序

代码语言:javascript
复制
List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge()); 

更新:在Java8之后,您可以使用开箱即用的lambda表达式,例如:

代码语言:javascript
复制
List<Customer> activeCustomers = customers.stream()
                                          .filter(Customer::isActive)
                                          .collect(Collectors.toList());                                      
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/93417

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档