支持布尔查询的内存数据结构

时间:2010-05-20 13:28:25

标签: java data-structures boolean-logic

我需要将数据存储在内存中,我将一个或多个键字符串映射到对象,如下所示:

"green", "blue" -> object1
"red", "yellow" -> object2

因此,在Java中,数据结构可能会实现:

Map<Set<String>, V>

我需要能够有效地接收对象列表,其中字符串匹配一些布尔标准,例如:

("red" OR "green") AND NOT "blue"

我在Java工作,所以理想的解决方案是现成的Java库。但是,如果有必要,我愿意从头开始实施。

有人有什么想法吗?如果可能的话,我宁愿避免使用内存数据库的开销,我希望能有一些与HashMap相当的速度(或至少相同的数量级)。

9 个答案:

答案 0 :(得分:6)

实际上,我喜欢这个问题,所以我按照我之前的答案精神实施了一个完整的解决方案:

http://pastebin.com/6iazSKG9

一个简单的解决方案,不是线程安全或任何东西,但我觉得很有趣,也是一个很好的起点。

编辑:根据要求进行一些详细说明


请参阅单元测试以了解使用情况。

有两个界面DataStructure<K,V>Query<V>。 DataStructure的行为有点像地图(在我的实现中它实际上与内部映射一起工作),但它也提供了可重用和不可变的查询对象,可以像这样组合:

    Query<String> combinedQuery = 
    structure.and(
                    structure.or(
                            structure.search("blue"), 
                            structure.search("red")
                    ),
                    structure.not(
                            structure.search("green")
                    )
    );

(查询标记为(蓝色或红色)和非绿色的对象的查询)。此查询是可重复使用的,这意味着只要更改了支持映射,它的结果就会发生变化(类似于ITunes智能播放列表)。

查询对象已经是线程安全的,但支持映射不是,因此这里有一些改进空间。此外,查询可以缓存它们的结果,但这可能意味着必须扩展接口以提供清除方法(有点像Wicket模型中的分离方法),这不会很漂亮。

至于许可:如果有人想要这个代码,我会很乐意把它放在SourceForge等......

肖恩

答案 1 :(得分:1)

标准是否适合位图索引:http://en.wikipedia.org/wiki/Bitmap_index

答案 2 :(得分:0)

我想说最简单的方法就是简单地做一个递归过滤和切割器,例如评估X AND Y,其中X被评估为空集。

然而,映射需要从标记(例如“红色”或“蓝色”)到对象集

递归的基本情况(解析原子标记)将是此映射中的简单查找。 AND将使用intersection,OR使用union实现,等等。

答案 3 :(得分:0)

查看Apache Commons - Collections project。他们有很多很棒的东西你可以使用,特别是CollectionUtils类来执行强大的基于集合的逻辑。

例如,如果您的值存储在HashMap中(如另一个答案所示),如下所示:

myMap["green"] -> obj1
myMap["blue"] -> obj1
myMap["red"] -> obj2
myMap["yellow"] -> obj2

然后检索匹配的结果:("red" or "green") and not "blue您可能会这样做:

  

CollectionUtils.disjunction(CollectionUtils.union(myMap.get(“red”),myMap.get(“green”)),myMap.get(“blue”))

答案 4 :(得分:0)

您可以将字符串键映射到二进制常量,然后使用位移来生成适当的掩码。

答案 5 :(得分:0)

我真的认为某种类型的数据库解决方案是您最好的选择。 SQL轻松支持通过

查询数据
(X and Y) and not Z

答案 6 :(得分:0)

答案 7 :(得分:0)

Google Collections SetMultimap看起来像是获取底层结构的简单方法,然后将其与Maps静态过滤器结合使用,以获得所需的查询行为。

施工会像

那样
smmInstance.put(from1,to1);
smmInstance.put(from1,to2);
smmInstance.put(from2,to3);
smmInstance.put(from3,to1);
smmInstance.put(from1,to3);
//...

查询看起来像

valueFilter = //...build predicate
Set<FromType> result = Maps.filterValues(smmInstance.asMap(),valueFilter).keySet()

你可以做任何花哨的构建谓词,但是Predicates有一些方法可能足以包含/不包含样式查询。

答案 8 :(得分:0)

我无法找到满意的解决方案,因此我决定自己制作并将其作为开源(LGPL)项目发布,找到它here