【问题标题】:In-memory data structure that supports boolean querying支持布尔查询的内存数据结构
【发布时间】:2010-05-20 13:28:24
【问题描述】:

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

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

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

Map<Set<String>, V>

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

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

我正在使用 Java,因此理想的解决方案是现成的 Java 库。但是,如有必要,我愿意从头开始实施。

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

【问题讨论】:

  • 在您的示例中,“绿色”是否映射到 object1?还是只有“绿色”和“蓝色”映射到 object1?
  • "green" 和 "blue" 就像 object1 上的 "tags" - 然后您可以通过对这些标签的布尔查询来选择对象。
  • “绿色”也能映射到一些object3吗?

标签: java data-structures boolean-logic


【解决方案1】:

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

http://pastebin.com/6iazSKG9

我猜这是一个简单的解决方案,不是线程安全的或其他任何东西,但很有趣并且是一个很好的起点。

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


查看单元测试的用法。

有两个接口,DataStructure&lt;K,V&gt;Query&lt;V&gt;。 DataStructure 的行为有点像地图(在我的实现中它实际上与内部地图一起使用),但它也提供了可重用和不可变的查询对象,可以像这样组合:

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

(搜索标记为(蓝色或红色)而不是绿色的对象的查询)。这个查询是可重用的,这意味着它的结果会随着背景地图的改变而改变(有点像 iTunes 智能播放列表)。

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

至于许可:如果有人想要此代码,我很乐意将其放在 SourceForge 等...

肖恩

【讨论】:

  • 有趣,但我没有看到更早的答案 - 您能否扩展一下其工作原理背后的基本思想?您会考虑将您的代码置于开源许可(例如 LGPL)之下吗?
  • 我删除了我之前的答案,对不起。我会在我的回答中详细说明
  • 酷。一些想法:它似乎创建了相当多的中间 ArrayLists - 我想知道是否可以在没有这些的情况下完成(也许返回一个惰性 Iterable 而不是一个 Collection)。缓存中间结果会很有趣。我还想知道用启发式方法来确定 And 和 Or 应该以哪种方式处理参数以获得最大效率。
  • 您所看到的只是概念验证,30 分钟的编码。但我在 google 代码 (code.google.com/p/imds4j) 上创建了一个项目,如果您(或其他任何人)为它做出贡献,我会很高兴,我也很乐意在那里详细说明您的评论。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    我想说最简单的方法是简单地进行递归过滤和切割器,例如在评估 X AND Y 时,其中 X 已被评估为空集。

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

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

    【讨论】:

      【解决方案4】:

      查看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"))

      【讨论】:

      • 我认为这还不够,因为它只允许一个绿色对象、一个蓝色对象等。
      • 只是 CollectionUtils 中一些工具和实用程序的快速(非功能性!)示例。我现在正在玩它,很快就会回复 - 有趣的问题!
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

          【讨论】:

            【解决方案8】:

            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 有一些方法可能足以进行包含/不包含样式查询。

            【讨论】:

              【解决方案9】:

              我没能找到令人满意的解决方案,所以我决定自己做一个开源 (LGPL) 项目,找到它here

              【讨论】:

                猜你喜欢
                • 2012-05-03
                • 1970-01-01
                • 1970-01-01
                • 2014-01-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多