假设您有一个由数百个内存中对象组成的集合,您需要查询此列表以返回与某些SQL或查询之类的条件匹配的对象。例如,您可能有一个汽车对象列表,并且希望返回20世纪60年代生产的所有汽车,车牌以AZ开头,按汽车型号的名称排序。
我知道JoSQL,有没有人用过它,或者对其他/自主开发的解决方案有任何经验?
发布于 2008-09-18 15:29:50
我在一个生产应用程序中使用过Apache Commons JXPath。它允许您将XPath表达式应用于Java语言中的对象图。
发布于 2012-07-30 05:02:32
过滤是实现此目的的一种方法,正如在其他答案中所讨论的。
不过,过滤是不可伸缩的。从表面上看,时间复杂度似乎是O(n) (即,如果集合中的对象数量将增长,则时间复杂度已经不可扩展),但实际上,因为需要根据查询对每个对象应用一个或多个测试,所以时间复杂度更准确地是O(n,t),其中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 central。如果你觉得这对你有帮助,请给这个答案加分!
发布于 2014-03-07 00:52:59
是的,我知道这是一个古老的帖子,但技术每天都会出现,答案会随着时间的推移而改变。
我认为这是一个用LambdaJ解决它的好问题。你可以在这里找到它:http://code.google.com/p/lambdaj/
下面是一个示例:
查找活跃客户// (可选版本)
List<Customer> activeCustomers = new ArrayList<Customer>();
for (Customer customer : customers) {
if (customer.isActive()) {
activeCusomers.add(customer);
}
} LambdaJ版本
List<Customer> activeCustomers = select(customers,
having(on(Customer.class).isActive())); 当然,拥有这样的美感会对表演产生影响(有点...平均2次),但是你能找到可读性更好的代码吗?
它有很多很多的功能,另一个例子是排序:
排序迭代
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());
}
}); 使用λ的排序
List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge()); 更新:在Java8之后,您可以使用开箱即用的lambda表达式,例如:
List<Customer> activeCustomers = customers.stream()
.filter(Customer::isActive)
.collect(Collectors.toList()); https://stackoverflow.com/questions/93417
复制相似问题