题
假设你已经收集了几百存中的对象,并需要查询这个名单返回匹配对象的一些SQL或条件,如查询。例如,可能有一个名单的汽车的对象,你要返回所有的汽车在1960年代,车牌,开始与亚利桑那州,下令通过这辆车的名字模型。
我知道关于 JoSQL, 有人用这个,或是有任何经验与其他/本土解决方案?
解决方案
我有用 Apache Commons JXPath 在生产中的应用。它可以应用XPath表以图表的对象。
其他提示
筛选是这样做的一个办法,作为讨论的其他的答案。
筛选是不可扩展。表面上时间的复杂性似乎是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(收集引擎查询).这基本上是一个非sql query引擎进行检索的对象Java集合的使用SQL样的查询,没有开销的循环的集合。它是建立在上述想法,再加上更多一些。免责声明:我是作者。这是开放源代码和在家中心。 如果你发现它很有帮助,请投票,这个答案!
是的,我知道这是一个古老的职位,但技术出现的日常和答案将会改变的时间。
我认为这是一个很好的问题要解决它与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());
}
});
排序与lambda
List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());
如果你需要一个单一的具体匹配,你可以有级实施比较,然后创建一个独立的目的与所有的散列领域包括在内,并用它来返回该索引的匹配。当你想找到多于一个(潜在的)目集合中,你就必须转向一个图书馆等JoSQL(其中有的工作以及在琐碎的情况下,我已经用它为)。
在一般情况下,我倾向于嵌入Derby到甚至我的小型应用程序,使用休眠注释的定义我的模型类和我们休眠处理缓存方案把一切都快。
我会用比较,需要一系列的年和许可证板模式为的输入参数。然后只是迭代过你的收集和复制的对象,相匹配。你很可能最终使整个软件包的定义比较这种做法。
的 Comparator
选项是不错的,特别是如果您使用匿名的类别(以创建冗余的类项目),但最终当你看看流动的比较,这是很多只是喜欢循环的整个集合自己,指定完全条件进行匹配项目:
if (Car car : cars) {
if (1959 < car.getYear() && 1970 > car.getYear() &&
car.getLicense().startsWith("AZ")) {
result.add(car);
}
}
然后是排序...这可能是一个痛苦的背后,但幸运的是有类 Collections
及其 sort
方法,其中一个接一个 Comparator
...