当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何在Java中查询对象集合(Criteria/SQL-like)?》经验,为你挑选了3个好方法。

假设您有几百个内存中对象的集合,并且您需要查询此List以返回与某些SQL或条件(如查询)匹配的对象.例如,您可能拥有一个汽车列表对象,并且您想要返回在20世纪60年代制造的所有汽车,车牌以AZ开头,按车型名称排序.

我知道JoSQL,有没有人使用过这个,或者有其他/本土解决方案的经验?



1> npgall..:

过滤是实现此目的的一种方式,如其他答案中所述.

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

因此,随着将额外对象添加到集合中和/或随着查询中的测试数量的增加,性能将降低.

还有另一种方法可以使用索引和集合理论.

一种方法是在存储在集合中的对象中字段构建索引,然后在查询中对其进行测试.

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

'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中心.如果您觉得它有用,请upvote这个答案!



2> Eric Weilnau..:

我在生产应用程序中使用了Apache Commons JXPath.它允许您将XPath表达式应用于Java中的对象图.



3> Federico Pia..:

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

我认为使用LambdaJ解决它是一个很好的问题.您可以在此处找到它:http: //code.google.com/p/lambdaj/

这里有一个例子:

寻找活跃的客户//(可转换的版本)

List activeCustomers = new ArrayList();  
for (Customer customer : customers) {  
  if (customer.isActive()) {  
    activeCusomers.add(customer);  
  }  
}  

LambdaJ版本

List activeCustomers = select(customers, 
                                        having(on(Customer.class).isActive()));  

当然,拥有这种美感会影响性能(有点......平均2次),但是你能找到更易读的代码吗?

它有许多功能,另一个例子可能是排序:

排序迭代

List sortedByAgePersons = new ArrayList(persons);
Collections.sort(sortedByAgePersons, new Comparator() {
        public int compare(Person p1, Person p2) {
           return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
        }
}); 

用lambda排序

List sortedByAgePersons = sort(persons, on(Person.class).getAge()); 

推荐阅读
mobiledu2402852413
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有