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

标签 java sql collections

假设您有一个包含数百个内存对象的集合,并且您需要查询此 List 以返回与某些 SQL 或 Criteria 类查询匹配的对象。例如,您可能有一个 Car 对象列表,并且您希望返回 1960 年代制造的所有汽车,车牌以 AZ 开头,按车型名称排序。

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

最佳答案

过滤是执行此操作的一种方法,如其他答案中所述。

过滤是不可扩展的。从表面上看,时间复杂度似乎是 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 中心。 如果你觉得有帮助,请点赞这个答案!

关于java - 如何在 Java 中查询对象集合(Criteria/SQL-like)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/93417/

相关文章:

c# - 从方法返回 List<T> 的性能是否与返回 Collection<T> 不同?

java - 数学加法代码,尝试在正确答案后结束

Java安全警告

mysql - 当我插入记录时关系表不更新

mysql - 如果表中的所有列都是某个唯一键的一部分,可以吗?

entity-framework - 将 Entity Framework 实体集合从 DAL 传递到业务层的最佳方法?

ruby-on-rails - 从has_many中删除对象,但是不删除Rails中的原始记录?

java - 为什么 JPA 使用 javax.persistence.NoResultException

java - File.listFiles() 和区分物理文件夹和虚拟文件夹

sql - Hive Query,有什么好的方法可以优化这些并集?